UseEffect挂钩未更新状态

时间:2020-08-21 12:10:34

标签: javascript reactjs

我正在关注this example,但使用的是功能组件。我的字段在整个状态下都受到控制,并且没有问题。但是,我所有的更新状态的功能都没有起作用:

function FormFieldTest() {

    const [state, setState] = useState({
        username: '',
        usernameValid: false,
        formValid: false,
        errorMsg: {}
    });

    useEffect(()=> {
        validateUsername();
        validateForm();
    },[state.username]);

    const updateUsername = (username) => {
        setState({...state, username: username});
    }

    const validateUsername = () => {
        let username = state.username;
        let usernameValid = true;
        let errorMsg = {...state.errorMsg};

        if(username.length < 3) {
            usernameValid = false;
            errorMsg.username = "Must be at least 3 characters long."
        }
        setState({...state,
            usernameValid: usernameValid,
            errorMsg: errorMsg
        });
    }

    const validateForm = () => {
        const usernameValid = state.usernameValid;

        setState({
            ...state,
            formValid: usernameValid
        });
    }

    return (
        <div className="container">
            <form>
                <div className="form-group">
                    <label htmlFor="username">Username</label>
                    <ValidationMessage valid={state.usernameValid} message={state.errorMsg.username} />
                    <input type="text" id="username" name="username" className="form-field" value={state.username} onChange={(e)=>updateUsername(e.target.value)} />
                </div>
            </form>
        </div>
    )
}

export default FormFieldTest;

validateForm和validateUsername都可以正常工作,只是它们没有设置状态。怎么会来?

2 个答案:

答案 0 :(得分:3)

注意:如果在setEffect中使用setState更新状态并重新渲染再次运行,并且useEffect再次更改相同状态并再次循环,则可能会创建一个无限循环。

将setState替换为该更改:

 setState(state => ({ ...state, username: username }));

答案 1 :(得分:0)

首先,您需要向其中useEffect添加在dependencies中调用的方法

使用useCallback钩子编写函数,而不是在每次渲染后创建新函数。

并且您必须将所有内容置于可以在此期间更改的依赖项中,以便在更改后具有其新值,因为它们将被记住

我更新了您的代码并将其放在此处,请检查它是否是您想要的?

https://codesandbox.io/s/zealous-grothendieck-y438z?file=/src/App.js