从 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 }