8

I would like to set multiple state values with React useState hook, so that I can I update them separately with useEffect hook. I have the following code:

import React, { useState } from "react";

const initialValues = {
  phone: "",
  email: ""
};

const App = () => {
  const [order, setOrder] = useState("");
  const [paid, setPaid] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState(initialValues);

  return (
    <div className="App">
    </div>
  );
};

export default App;

But when I inspect the App with React DevTools, I see multiple "State" values for my hook, instead of "order", "paid", "submitting" etc.

Here is the link to my codesandbox.

Where is my mistake? How can I set multiple state values to update them separately later on?

jupiteror
  • 1,085
  • 3
  • 24
  • 50
  • 1
    There is nothing wrong with your solution. The name you give to those states is only local to your component when you destructure the array that useState returns. React does not know about the name you give to those elements in the array that useState returns. Don't worry about the generic name that shows up in dev-tools, just try your solution and you'll see it works. For something that shows up in dev-tools, you could use useDebugValue: https://reactjs.org/docs/hooks-reference.html#usedebugvalue – Olavi Apr 08 '20 at 17:30
  • 1
    @olpe Thank you very much. You can post your comment as an answer and I will accept it. – jupiteror Apr 09 '20 at 12:31
  • 1
    Alright, I was actually wondering whether it should be a comment or an answer. – Olavi Apr 12 '20 at 16:16

3 Answers3

21

You can make one state with useState hook and put every value there like this.

import React, { useState } from "react";

const initialValues = {
  phone: "",
  email: ""
};

const App = () => {
  const [state, setState] = useState({
     order:'',
     paid: false,
     submitting: false,
     loading: false,
     data: initialValues
  });
  // example of setting this kind of state
  const sampleChanger = () => {
     setState({...state, paid: true, order: 'sample'});
  }
// etc...
Shotiko Topchishvili
  • 2,663
  • 10
  • 20
  • 4
    I believe this pattern will bypass React's ability to detect change in state. It might not matter in tiny simple apps, but can lead to issues on complex apps. This guy's comment is relevant and helpful: https://stackoverflow.com/a/57102754/3684449 Also I believe `useReducer()` exists for exactly this. Docs: https://stackoverflow.com/questions/53574614/multiple-calls-to-state-updater-from-usestate-in-component-causes-multiple-re-re – lance.dolan Oct 04 '21 at 02:56
  • 1
    so grateful for this answer! Thanks man! – Ezeeroc Nov 10 '21 at 17:19
5

There is nothing wrong with your solution. The name you give to those states is only local to your component when you destructure the array that useState returns. React does not know about the name you give to those elements in the array that useState returns. Don't worry about the generic name that shows up in dev-tools, just try your solution and you'll see it works.

For something that shows up in dev-tools, you could use useDebugValue.

Olavi
  • 821
  • 4
  • 12
1

You haven't made a mistake. If you want to use separate hooks like this, this is how they will appear in React DevTools. If you want to have name label associated with each hook, check out this StackOverflow answer:

Is there any way to see names of 'fields' in React multiple state with React DevTools when using 'useState' hooks

tombraider
  • 1,127
  • 1
  • 11
  • 19