JohnFajardo
JohnFajardo

Reputation: 95

UseEffect hook not updating state

I'm following this example but using a functional component. My field is controlled throught state and it works with no problem. However, none of my functions that update the state are working:

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;

Both the validateForm and validateUsername are working, except they're not setting the state. How come?

Upvotes: 0

Views: 112

Answers (2)

Baruch Mashasha
Baruch Mashasha

Reputation: 979

Attention: using setState inside useEffect maybe create an infinite loop, if you update state inside it and re-render run again and the useEffect change the same state again and loop again.

Replace your setState to this change:

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

Upvotes: 3

Hovakimyan
Hovakimyan

Reputation: 558

First of all, you need to add methods called in useEffect to it dependencies

Write your functions with useCallback hooks as you use them, and wasn't to create new function after every render.

And you must put everything in dependencies which can be changed during the time to have their new values after the change, es they will be memoized

I updated your code and put it here, please check is it what you want?

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

Upvotes: 0

Related Questions