CCCC
CCCC

Reputation: 6469

React - the value of state which depends on another state cannot be updated

Step to reproduce

  1. After entering Codesandbox Console, you can see the initial value of typeA and allTypes.
    enter image description here
  2. Click "Update type A" button
  3. In Console, you can see the updated value of typeA and allTypes.
    enter image description here

Expected Behaviour
In allTypes, the value of field typeA should be "different value".

Actual Behaviour
the value of field typeA still remain unchanged.

Questions

  1. Why doesn't the value of field typeA update?
  2. How to fix it?

App.js

import "./styles.css";
import { useState, useEffect } from "react";

export default function App() {
  const [typeA, setTypeA] = useState("01");
  const [typeB, setTypeB] = useState("abc");

  const [allTypes, setAllTypes] = useState({
    typeA: [typeA],
    typeB
  });
  console.log({ typeA }); // updated successfully
  console.log({ allTypes }); // the value of typeA remain unchanged
  return (
    <div>
      <button
        onClick={() => {
          setTypeA("different value");
        }}
      >
        Update type A
      </button>
    </div>
  );
}

Codesandbox
https://codesandbox.io/s/jovial-lichterman-w1kbph?file=/src/App.js

Upvotes: 0

Views: 34

Answers (1)

Nathanael
Nathanael

Reputation: 1002

The argument of useState is an initializer which doesn't update beyond the initial render. You can useMemo to achieve your intended behavior. You can't "feed" a value into the argument of useState.

const [typeA, setTypeA] = useState("01");
const [typeB, setTypeB] = useState("abc");

const allTypes = useMemo(() => {
   return {typeA: [typeA], typeB}
},[typeA, typeB])

You can do it without useMemo as well, but the object reference will be recreated every render.

Upvotes: 2

Related Questions