Use the appropriate API provided.

not

const [count, setCount] = useState(0); 
const increment = () = > setCount(count + 1); 
const decrement = () = >SetCount (count -1);
Copy the code

Instead,

const [count, setCount] = useState(0); 
const increment = () = > setCount((prevCount) = > prevCount + 1); 
const decrement = () = > setCount((prevCount) = >PrevCount -1);
Copy the code

SetState takes two types of arguments.

The interface that receives the next state as a parameter directly.

setState(newState);
Copy the code

An interface that takes a parameter and computes a new state from the previous state.

setState((prev) = > createNewStateFromPrevState(prev));
Copy the code

Counter application increments are often used as examples in the topic of introductory useState articles, meaning “the function increments the previous count by one.” Therefore it is appropriate to apply setCount ((prev) => prev + 1) to the second function interface. The same is true of diminishing.

A situation where something goes wrong

You might think the first encoding is correct

It just so happens that the sample works fine and may have hard-to-find errors.

For example, suppose you modularize useCounter as a utility function that you can use anywhere in your application.

export const useCounter = (init: number = 0) = > {
    const [count, setCount] = useState(init);
    const increment = () = > setCount(count + 1);
    const decrement = () = >SetCount (count -1);
    return { count, increment, decrement };
};
Copy the code

A user of useCounter found that increment and Decrement did not accept parameters and could only operate on one difference, and that he could only call it twice if he wanted to apply it and change it twice

import { useCounter } from". / useCounter ";export default function App() { 
  const { count, increment, decrement } = useCounter(10);   
  const incrementDouble = () = > { 
    increment(); 
    increment(); 
  }; 
  const decrementDouble = () = > { 
    decrement(); 
    decrement(); 
  };   return ( 
    <div className="App"> 
      <h1>Count: {count}</h1> 
      <button onClick={incrementDouble}>+ 2</button> 
      <button onClick={decrementDouble}>2 -</button> 
    </div> 
  ); 
}
Copy the code

The code above doesn’t work. If you click the +2 button, it seems that 2 is added but only +1 is added

If the button is clicked once, the increment (or decrement) is called twice, so it should change twice. Why is that?

Because it just passes the same value to setCount over and over again.

Count is just a constant, not a variable value

export default function App() {
  const [count, setCount] = useState(0);
  const increment = () = > setCount(count + 1);
  const decrement = () = > setCount(count - 1);

  return (
    <div className="App">
      <h1>Count: {count}</h1>
      <button onClick={increment}>+ 1</button>
      <button onClick={decrement}>- 1</button>
    </div>
  );
}
Copy the code

When count === 20, the contents of the component are written as follows

export default function App() {
const [20, setCount] = useState(0);
const increment = () = > setCount(20 + 1);
const decrement = () = > setCount(20 - 1);

  return (
    <div className="App">
      <h1>Count: {20}</h1>
      <button onClick={increment}>+ 1</button>
      <button onClick={decrement}>- 1</button>
    </div>
  );
}
Copy the code

You can see that we’re just passing 21 to the actual setCount.

So the example I mentioned earlier should be written as:

const incrementDouble = () = > {
  setCount(20 + 1);
  setCount(20 + 1);
};
Copy the code

This function simply repeats the process of updating the status to 21 twice.

The functions passed to setState are state transition instructions

So let’s improve the code!

export const useCounter = (init: number = 0) = > {
  const [count, setCount] = useState(init);

  const increment = () = > setCount((prevValue) = > prevValue + 1);
  const decrement = () = > setCount((prevValue) = > prevValue - 1);

  return { count, increment, decrement };
};
Copy the code

This code works.

Write setCount ((prevValue) => prevValue + 1) instead of setCount (count + 1).