从 React 钩子中读取状态
Read state from React hooks
我有以下代码
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
时,没有出现电子邮件错误。这就像我没有在我的 return 语句中得到最新的状态变化。我做错了什么?
首先,要存储大对象,就像在本例中,使用 useReducer
而不是 useState
。
通过键入 const newState = state;
,您将分配相同的对象,因此您仍将使用相同的对象。使用 const newState = {...state}
或类似的东西。
让我们往下看:
const showEmailError = state.errors.email;
[...]
{state.errors.email[0]}
您的 state.errors 属性 是布尔值,因此它没有任何嵌套对象。
在useEffect中,你需要传递dependencies数组,它会被跟踪并在任何变化时调用函数。要只调用一次,传递空数组:
useEffect(() => {
console.log(state);
}, []);
如果您想记录每个状态更改,请将状态作为依赖项传递。
setState
认为没有任何变化,因为您每次都向它传递相同的 state
对象。在每次更新时创建一个新对象:
const newState = { ...state };
我在评论中给了你提示,但你好像忽略了它。你不应该直接改变状态对象,因为当你调用 setState 时,React 会将它与你的原始状态对象引用进行比较(感谢 Ross 在评论中指出)。因为无论如何你已经改变了它并且 React 没有找到任何改变的属性,你的组件没有更新因此 useEffect
钩子没有被调用。在工作之前创建对状态对象的新引用。这是您需要做的:
替换
const newState = state;
和
const newState = { ...state }
我有以下代码
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
时,没有出现电子邮件错误。这就像我没有在我的 return 语句中得到最新的状态变化。我做错了什么?
首先,要存储大对象,就像在本例中,使用 useReducer
而不是 useState
。
通过键入 const newState = state;
,您将分配相同的对象,因此您仍将使用相同的对象。使用 const newState = {...state}
或类似的东西。
让我们往下看:
const showEmailError = state.errors.email;
[...]
{state.errors.email[0]}
您的 state.errors 属性 是布尔值,因此它没有任何嵌套对象。
在useEffect中,你需要传递dependencies数组,它会被跟踪并在任何变化时调用函数。要只调用一次,传递空数组:
useEffect(() => {
console.log(state);
}, []);
如果您想记录每个状态更改,请将状态作为依赖项传递。
setState
认为没有任何变化,因为您每次都向它传递相同的 state
对象。在每次更新时创建一个新对象:
const newState = { ...state };
我在评论中给了你提示,但你好像忽略了它。你不应该直接改变状态对象,因为当你调用 setState 时,React 会将它与你的原始状态对象引用进行比较(感谢 Ross 在评论中指出)。因为无论如何你已经改变了它并且 React 没有找到任何改变的属性,你的组件没有更新因此 useEffect
钩子没有被调用。在工作之前创建对状态对象的新引用。这是您需要做的:
替换
const newState = state;
和
const newState = { ...state }