reactjs - 在我的应用程序中实现状态的正确方法是什么
问题描述
我正在为我的健身房构建一个小应用程序,让会员可以预订我们的六个串联停车位(3x2 网格)中的一个。我试图构建这个应用程序只使用钩子作为一种学习方式,但无法弄清楚如何实现状态(下面的代码片段)。
基本上,我有一个 ParkingLot 组件,它映射到由六个停车位对象组成的数组并呈现一个 ParkingSpace 组件。当您单击空间的“保留”时,会加载一个 FormContainer 组件,该组件要求输入名称和所采用的类。我在“Thinking in React”中读到状态不应该是任何可以从其他地方派生的信息,这让我认为只有这个用户输入应该是我的状态,但它去哪里以及如何访问它在组件之间?我的直觉告诉我它应该存在于 ParkingLot 组件中。这个对吗?如果是这样,应该如何使用钩子来构建它?
const parkingLot = (props) => {
const spaces = [{id: 1, name: "Chase", classTaken: "Level 2", reserved: true, form: false},
{id: 2, name: "", classTaken: "", reserved: false, form: false},
{id: 3, name: "", classTaken: "", reserved: false, form: false},
{id: 4, name: "", classTaken: "", reserved: false, form: false},
{id: 5, name: "", classTaken: "", reserved: false, form: false},
{id: 6, name: "", classTaken: "", reserved: false, form: false}];
return spaces.map(space => {
if (space.form === false) {
return (
<div>
<ParkingSpace key={space.id} id={space.id} name={space.name} classTaken={space.classTaken} reserved={space.reserved} />
{
(space.reserved)
? <button>Check Out</button>
: <button>Reserve</button>
}
</div>
)
} else {
<FormContainer id={space.id}/>
}
});
}
停车位组件
const space = (props) => {
return (
<div>
<h4>Parking Space {props.id}</h4>
{
(props.reserved === false)
? <div>
<p>Currently Available</p>
</div>
: <div>
<p>Checked Out By: {props.name}</p>
<p>Taking Class: {props.classTaken}</p>
</div>
}
</div>
)
};
预先感谢您的帮助。这是我关于 SO 的第一篇文章,所以请让我知道我是否可以更好地澄清或格式化任何内容。
解决方案
spaces
数据用于确定 ParkingLot 组件的呈现方式——是否应显示表单以及描述每个空间的数据。因此,您不应该(也不能)将该数据存储在 Space 组件上。
您应该将整个spaces
数据转换为 ParkingLot 组件上的单个状态(六个单独的状态也可以工作,但我认为这不是最好的方法)。然后,您可以像现在一样使用这些数据来渲染每个 Space 组件。要使复杂对象进入状态而不破坏它,您可以使用react-hooks-object-state
允许使用挂钩进行部分对象更新。
import useObjectState from 'react-hooks-object-state';
const ParkingLot = (props) => {
const [spaces, setSpaces] = useObjectState({
space1: {id: 1, name: "Chase", classTaken: "Level 2", reserved: true, form: false},
space2: {id: 2, name: "", classTaken: "", reserved: false, form: false},
space3: {id: 3, name: "", classTaken: "", reserved: false, form: false},
space4: {id: 4, name: "", classTaken: "", reserved: false, form: false},
space5: {id: 5, name: "", classTaken: "", reserved: false, form: false},
space6: {id: 6, name: "", classTaken: "", reserved: false, form: false}
});
...
}
那么问题将是如何更新数据。在不知道您的 FormContainer 组件是什么样子的情况下,您可以简单地将 setter 函数(setSpaces
从上面)作为道具传递给 FormContainer,并在提交表单时在 FormContainer 中调用它。以下是更新可能的样子:
const FormContainer = (props) => {
const handleFormSubmit = () => {
props.setSpaces({
space5: {id: 5, name: "John Doe", classTaken: "Level 3", reserved: true, form: false}
});
};
...
}
这将更新spaces
ParkingLot 状态下空间 5 的数据,而不会影响任何其他空间数据。我已经spaces
从数组更改为对象,因为useObjectState
期望数据类似于setState
经典组件中的数据。
推荐阅读
- azure-devops - Azure DevOps - 更改登录电子邮件
- python - Daphne 服务器在基于 Django Channels 的架构中执行了一个很长的进程后停止
- json - SSIS 无法访问组件的高级编辑器
- sql-server - SQL 服务器。插入和删除的表是否有默认列?
- bash - 变量为空时不匹配正则表达式
- wpf - 现有桌面应用程序的 OAuth 2.0 工作流程
- flutter - 如何使用包含ä、ö、ü(不同于 US-ASCII 的字符集)的 csv dart 包转换 csv 文件?
- java - UFT 自动化脚本不适用于特定的远程计算机登录
- mysql - MYSQL比较不同数据库中的客户数据
- javascript - Vue表单向导防止退步