Home > other >  React button disabled property not updating
React button disabled property not updating

Time:07-06

I have trouble using the disabled property on a button with react. The property works if I hard code a value in the input but the button is not re-rendered automatically when the state is updated through an input change.

export default function App() {
  const [user, setUser] = useState({ email: "" });

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <form>
        <div>
          <div>
            <label htmlFor="email">
              Email
            </label>
          </div>
          <input
            type="text"
            name="email"
            id="email"
            placeholder=""
            onChange={(e) =>
              setUser((previous) => {
                previous.email = e.target.value;
                return previous;
              })
            }
          />
        </div>
        <button type="submit" disabled={user.email === ""}>
          Button
        </button>
      </form>
    </div>
  );
}

The problem can be experienced live here: https://codesandbox.io/s/suspicious-kapitsa-z2zj3m?file=/src/App.js

CodePudding user response:

In the mentioned code previous points to the same reference as the new state you are setting. For complex state variables like objects React finds diff of object using shallow comparison and since both variables point to the object there is no rerender.

Creating a copy of the object which points to a different address in memory, and setting the state using that should fix it.

 setUser((previous) => {
                const newValue = { ...previous };
                newValue.email = e.target.value;
                return newValue;
              })

Link

That is why it is never a good idea to mutate state in React. Always create a new copy and make changes to that. This is the base of pure functions and functional programming.

CodePudding user response:

Just use:

(e) => setUser((previous) => ({...previous, email: e.target.value}))

You trying to mutate the previous state manually is what prevents React from detecting a change (because the reference stays the same)

Also, to use control forms properly, you need to add this prop to your input:

value={user.email}
  • Related