我有以下代码
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语句中没有得到最新的状态更改一样。我在做什么错了?
答案 0 :(得分:2)
我在注释中给了您提示,但好像您忽略了它。您不应像在调用setState时那样直接改变状态对象,React会将其与原始状态对象引用进行比较(感谢Ross在注释中指出)。由于您已经对其进行了突变并且React无法找到任何更改的属性,因此您的组件不会更新,因此不会调用useEffect
钩子。在工作之前,请创建对状态对象的新引用。这是您需要做的:
替换
const newState = state;
与
const newState = { ...state }
答案 1 :(得分:-1)
首先,要存储大对象(如本例所示),请使用useReducer
而不是useState
。
通过键入const newState = state;
,您将分配相同的对象,因此您将使用仍然相同的对象。使用const newState = {...state}
或类似的方式。
下面让我们看看:
const showEmailError = state.errors.email;
[...]
{state.errors.email[0]}
您的state.errors属性为布尔值,因此它没有任何嵌套对象。
在useEffect中,您需要传递依赖项数组,该数组将被跟踪并在发生任何更改时调用函数。要只调用一次,请传递空数组:
useEffect(() => {
console.log(state);
}, []);
如果您想记录每个状态更改,请将状态作为依赖项传递。
答案 2 :(得分:-1)
q = urllib.parse.quote_plus(s)
=> 'Marta+Ga%C5%82szewska'
认为没有任何变化,因为您每次都将同一个setState
对象传递给它。在每次更新时创建一个新对象:
state