5

I have the following code inside a react functional component. When I click the button and run the handler, an error occurs: Invalid hook call. Hooks can only be called inside of the body of a function component.

const handleClick = () => {
  const [count, setCount] = useState(x); // this is wrong
};

I tried to search for the fix, someone suggests:

const [count, setCount] = useState(0);

const handleClick = () => {
  setCount(x); // setCount is ok, but I cannot set other dynamic states
};

However, my count state is dynamic and I cannot initialize all from start. When I use class components, it was easy.

// old syntax from class components
state = {
  count: 0
};

const handleClick = () => {
  this.setState({
    other_count: x
  })
};

How to achieve the same effect for functional components?

wirher
  • 916
  • 1
  • 8
  • 26
5413668060
  • 326
  • 2
  • 15

2 Answers2

5

if you want to use state dynamically, use object as state.

Keep in mind with the immutability.

const [state, setState] = useState({ count: 0 });

const handleClick = () => {
  setState({...state, other_count: x });
}
kyun
  • 9,710
  • 9
  • 31
  • 66
4

You can use multiple states or an object in a single state.

First way:

const [count, setCount] = useState(0);
const [otherCount, setOtherCount] = useState(0);

const handleClick = () => {
  // count is already available to you.. so update the other state
  setOtherCount(x);
};

Second way:

const [compState, setCompState] = useState({ count: 0, other_count: 0 });

const handleClick = () => {
  setCompState(prevState => { ...prevState, other_count: x });
};

DEMO for the second way.

Kishor
  • 2,659
  • 4
  • 16
  • 34
  • will it fail if I update multiple states from different functions? For example `state = { a: 1, b: 2 }` and `setState({ ...state, a: 10 })` `setState({ ...state, b: 20 })` from different async functions, any race conditions? – 5413668060 Oct 21 '19 at 07:48
  • 1
    If you are updating in async functions, then you can use another way to update state. `setState(prevState => { ...prevState, a:10 })` – Kishor Oct 21 '19 at 08:03
  • @5413668060 You can check this link as well. I have used setTimeout to test async kind of behaviour. https://codesandbox.io/s/upbeat-bird-l97e4?fontsize=14 – Kishor Oct 21 '19 at 08:07