【React Hooks】为什么不应该写setCount(count + 1)

1,317 阅读2分钟

使用提供的适当 API。

不是

const [count, setCount] = useState(0); 
const increment = () => setCount(count + 1); 
const decrement = () => setCount(count — 1);

反而

const [count, setCount] = useState(0); 
const increment = () => setCount((prevCount) => prevCount + 1); 
const decrement = () => setCount((prevCount) => prevCount — 1);

setState 有两种类型的参数。

直接接收下一个状态作为参数的接口。

setState(newState);

一个接口,它接受一个参数,从以前的状态计算一个新的状态。

setState((prev) => createNewStateFromPrevState(prev));

计数器应用程序增量在 useState 介绍性文章的主题中经常作为示例出现,意思是“函数将前一个计数加 1”。
因此将setCount ((prev) => prev + 1) 应用于第二个函数接口是合适的。递减也是如此。

出现问题的情况

您可能认为第一种编码方式正确

碰巧样本工作正常,并且可能存在难以发现的错误。

例如,假设您将 useCounter 模块化为一个实用程序函数,您可以在应用程序的任何位置使用它。

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 };
};

useCounter 的一个用户,发现 increment 和 decrement 不接收参数,只能操作一个差值,想应用它并改变它两个, 他只能调用两次

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> 
  ); 
}

上面的这段代码不能正常工作。如果您单击 +2 按钮,似乎会添加 2 但只添加了 +1

如果按钮被点击一次,增量(或减量)被调用两次,所以它应该改变两次。为什么?

因为它只是一遍又一遍地将相同的值传递给 setCount。

count 只是一个常数,而不是一个变量值

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>
  );
}

当count === 20时,组件的内容写成如下

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>
  );
}

您可以看到我们只是将 21 传递给实际的 setCount。

所以我之前提到的示例应该写成:

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

该函数只是重复两次将状态更新为 21 的过程。

传递给 setState 的函数是状态转换指令

所以让我们改进代码!

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 };
};

此代码正常工作。

setCount ((prevValue) => prevValue + 1) 而不是写 setCount (count + 1)。