Search code examples
javascriptreactjsreact-hooksuse-effectuse-state

How to set the initial value of useState with the value of another state set in a useEffect hook?


  1. I get user data from Firestore in a useEffect hook and then put the data in a state. This part works fine.
const [profile, setProfile] = useState("")

useEffect(() => {
// Get user profile data from firestore.. 
    setProfile(userData) 
}, [])
  1. I have HTML radio inputs where user can change their gender but I need to set the initial gender (one they choose during sign-up) with a state.
const defaultGender = profile.gender
const [gender, setGender] = useState(defaultGender)

<input onChange={e => setGender(e.target.value)} type="radio" id="Man" name="gender" value="Man" checked={defaultGender === "Man"} /> <label htmlFor="Man">Man</label>

<input onChange={e => setGender(e.target.value)} type="radio" id="Woman" name="gender" value="Woman" checked={defaultGender === "Woman"} /> 
<label htmlFor="Woman">Woman</label>

The problem is, with this code, console.log(gender) returns undefined and I can not check (select) a different gender as it is stuck on Man.


Solution

  • Seems like you just need to:

    1. Use gender from the state (not defaultGender) for the checked input's prop.
    2. Update your gender state after the profile state updating.

    CodePen

    const { useState, useEffect, Fragment } = React;
    
    const Form = () => {
      const [profile, setProfile] = useState({});
      const [gender, setGender] = useState(profile.gender);
    
      useEffect(() => {
        // Assuming you have an async request here...
        const profile = { gender: "Woman" };
        setProfile(profile);
        setGender(profile.gender);
      }, []);
    
      return (
        <Fragment>
          <input
            onChange={(e) => setGender(e.target.value)}
            type="radio"
            id="Man"
            name="gender"
            value="Man"
            checked={gender === "Man"}
          />
          <label htmlFor="Man">Man</label>
          <input
            onChange={(e) => setGender(e.target.value)}
            type="radio"
            id="Woman"
            name="gender"
            value="Woman"
            checked={gender === "Woman"}
          />
          <label htmlFor="Woman">Woman</label>
        </Fragment>
      );
    };
    
    ReactDOM.render(<Form />, document.body);
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>