>我有以下代码
const initialState = {
values: {
email: '',
password: ''
},
touched: {
email: false,
password: false
},
errors: false,
isValid: false,
isLoading: false,
submitError: null
};
function SignIn(props) {
const [state, setState] = useState(initialState);
useEffect(() => {
console.log(state);
});
const handleFieldChange = (field, value) => {
const newState = state;
newState.submitError = null;
newState.touched[field] = true;
newState.values[field] = value;
newState.errors = true; // set to true just for test
setState(newState);
};
const showEmailError = state.errors.email;
return (
<div>
<TextField
className={classes.textField}
label="Email address"
name="email"
onChange={event => handleFieldChange('email', event.target.value)}
type="text"
value={state.email}
variant="outlined"
/>
{showEmailError && (
<Typography
className={classes.fieldError}
variant="body2"
>
{state.errors.email[0]}
</Typography>
)}
</div>
)
}
我遇到的问题是,当执行handFieldChange
时,不会出现电子邮件错误。就像我在返回语句中没有得到最新的状态更改一样。我做错了什么?
我在评论中给了你一个提示,但似乎你忽略了它。你不应该像调用 setState 时那样直接改变状态对象,React 会将其与原始状态对象引用进行比较(感谢 Ross 在评论中指出(。由于您已经对其进行了更改,并且 React 没有找到任何更改的属性,因此您的组件不会更新useEffect
因此不会调用钩子。在工作之前创建对状态对象的新引用。以下是您需要执行的操作:
取代
const newState = state;
跟
const newState = { ...state }
首先,要存储大型对象,就像在这种情况下一样,使用 useReducer
而不是 useState
。
通过键入const newState = state;
您将分配相同的对象,因此您将使用相同的对象。使用这样的const newState = {...state}
或sth。
让我们看看下面:
const showEmailError = state.errors.email;
[...]
{state.errors.email[0]}
您的 state.errors 属性是布尔值,因此它没有任何嵌套对象。
在useEffect中,你需要传递依赖数组,该数组将被跟踪并在任何更改时调用函数。要只调用它一次,请传递空数组:
useEffect(() => {
console.log(state);
}, []);
如果要记录每个状态更改,请将状态作为依赖项传递。
setState
认为没有任何变化,因为您每次都传递相同的state
对象。每次更新时创建一个新对象:
const newState = { ...state };