简体   繁体   English

从React钩子读取状态

[英]Read state from React hooks

I have the following code 我有以下代码

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

The problem that I have is that when the handFieldChange is executed, the email error does not appear. 我的问题是执行handFieldChange时,不会出现电子邮件错误。 It's like I don't get the latest state change in my return statement. 就像我在return语句中没有得到最新的状态更改一样。 What am I doing wrong? 我究竟做错了什么?

I gave you a hint in comments but it seems like you ignored it. 我在评论中给了您提示,但似乎您忽略了它。 You should not mutate the state object directly as when you call setState, React compares it with your original state object reference (thanks for Ross to point it out in comments). 您不应像在调用setState时那样直接改变状态对象,React会将其与原始状态对象引用进行比较(感谢Ross在注释中指出)。 Since you've already mutated it anyway and React doesn't find any changed properties, your component is not updated and hence useEffect hook is not called. 由于您已经对其进行了突变,并且React找不到任何更改的属性,因此不会更新您的组件,因此不会调用useEffect挂钩。 Create a new reference to your state object before working. 在工作之前,请创建对状态对象的新引用。 Here's what you need to do: 这是您需要做的:

Replace 更换

const newState = state;

with

const newState = { ...state }

First of all, to store big object, like in this case, use useReducer instead of useState . 首先,要存储大对象(如本例所示),请使用useReducer而不是useState

By typing const newState = state; 通过输入const newState = state; you're assigning same object, so you'll work with still same object. 您要分配相同的对象,因此您将使用相同的对象。 Use const newState = {...state} or sth like that. 使用const newState = {...state}或类似的东西。

Lets' look below: 让我们看下面:

const showEmailError = state.errors.email;
[...]
{state.errors.email[0]}

Your state.errors property is boolean, so it doesn't have any nested objects. 您的state.errors属性是布尔值,因此它没有任何嵌套对象。


In useEffect, you need to pass dependencies array, which will be tracked and call function on any change. 在useEffect中,您需要传递依赖关系数组,该数组将被跟踪并在发生任何更改时调用函数。 To call it only once, pass empty array: 要只调用一次,请传递空数组:

useEffect(() => {
    console.log(state);
}, []);

If u want to log every state changes, pass state as a dependency. 如果您想记录每个状态更改,请将状态作为依赖项传递。

setState thinks that nothing is changing because you're passing it the same state Object every time. setState认为没有任何变化,因为您每次都将相同的state Object传递给它。 Create a new Object on each update: 在每次更新时创建一个新的对象:

const newState = { ...state };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM