当前位置: 首页 > 知识库问答 >
问题:

为什么需要使用功能更新表单React useState?

宦翔飞
2023-03-14

我正在阅读关于功能更新的React Hook留档,请参阅以下引用:

“”和“-”按钮使用函数形式,因为更新的值基于以前的值

但是我看不出需要功能更新的目的是什么,它们和直接使用旧状态计算新状态有什么区别。

为什么React-useState钩子的更新程序函数需要函数更新表单?在哪些示例中,我们可以清楚地看到差异(因此使用直接更新会导致错误)?

例如,如果我从文档中更改此示例

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
    </>
  );
}

要直接更新count

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
    </>
  );
}

我看不到行为上的任何差异,也无法想象计数不会被更新(或者不会是最新的)。因为无论何时更改计数,都将调用onClick的新闭包,以捕获最新的count

共有3个答案

漆雕誉
2023-03-14

我已经回答了一个类似的问题,因为这是一个我不知道的经典问题,所以我决定将我的答案重新发布在这里,因为我认为这会增加一些价值。

如果更新依赖于在状态中找到的先前值,则应使用函数形式。如果在这种情况下不使用函数形式,那么代码有时会中断。

它为什么会断裂,何时断裂

React函数组件只是闭包,闭包中的状态值可能已经过时——这意味着闭包中的值与该组件处于React状态的值不匹配,这可能发生在以下情况案例:

1-异步操作(在本例中,单击“慢速添加”,然后多次单击“添加”按钮,稍后您将看到,当单击“慢速添加”按钮时,状态已重置为闭包内的状态)

const App = () => {
  const [counter, setCounter] = useState(0);

  return (
    <>
      <p>counter {counter} </p>
      <button
        onClick={() => {
          setCounter(counter + 1);
        }}
      >
        immediately add
      </button>
      <button
        onClick={() => {
          setTimeout(() => setCounter(counter + 1), 1000);
        }}
      >
        Add
      </button>
    </>
  );
};

2-在同一个闭包中多次调用update函数时

const App = () => {
  const [counter, setCounter] = useState(0);

  return (
    <>
      <p>counter {counter} </p>
      <button
        onClick={() => {
          setCounter(counter + 1);
          setCounter(counter + 1);
        }}
      >
        Add twice
      </button>
   
    </>
  );
}
充栋
2023-03-14

我最近偶然发现需要这个。例如,假设你有一个组件,它用一些元素填充一个数组,并且能够根据用户的一些操作追加到该数组(就像在我的例子中,我一次加载10个项目,因为用户保持向下滚动屏幕。代码看起来像这样:

function Stream() {
  const [feedItems, setFeedItems] = useState([]);
  const { fetching, error, data, run } = useQuery(SOME_QUERY, vars);

  useEffect(() => {
    if (data) {
      setFeedItems([...feedItems, ...data.items]);
    }
  }, [data]);     // <---- this breaks the rules of hooks, missing feedItems

...
<button onClick={()=>run()}>get more</button>
...

显然,您不能只将feedItems添加到useEffect钩子中的依赖项列表中,因为您在其中调用setFeedItems,所以您将进入一个循环。

救援功能更新:

useEffect(() => {
    if (data) {
      setFeedItems(prevItems => [...prevItems, ...data.items]);
    }
  }, [data]);     //  <--- all good now
高钱青
2023-03-14

状态更新在React中是异步的。因此,当您下次更新它时,它可能会有旧值。例如,比较这两个代码示例的结果:

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => {
        setCount(prevCount => prevCount + 1); 
        setCount(prevCount => prevCount + 1)}
      }>+</button>
    </>
  );
}

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => {
        setCount(count + 1); 
        setCount(count + 1)}
      }>+</button>
    </>
  );
}
 类似资料:
  • 问题内容: 我认为这个问题已经存在,但是我找不到。 我不明白,为什么必须要有一个功能接口才能使用lambda。考虑以下示例: 这可以正常工作,但是如果您取消注释行,则不会。为什么?以我的理解,编译器应该能够区分这两种方法,因为它们具有不同的输入参数。为什么我需要一个功能接口并炸毁我的代码? 编辑:链接的重复项没有回答我的问题,因为我在询问不同的方法参数。但是在这里,我得到了一些非常有用的答案,这要

  • 我只想问关于争论的事。方法名并不重要,但每个方法都采用不同参数的唯一顺序,因此Oracle可以实现这个特性,而不是让每个“lambda-interface”都有一个方法。

  • 我正在考虑使用React Relay或Apollo客户端。我喜欢GraphQL作为一种查询语言的想法,它可以针对任何API或数据存储执行。 然而,我感到惊讶的是,在一个简单的变化之后,需要手动(并且必须)更新存储/缓存,比如在列表中添加一个待办事项。以下是更新程序/更新功能的文档: http://facebook.github.io/relay/docs/en/mutations.htmlhttp

  • 问题内容: 在工作中,我们曾经以非常标准的OO方式对Python进行编程。最近,有几个人加入了实用的潮流行列。现在,他们的代码包含更多的lambda,映射和简化。我了解功能语言对并发性有好处,但对Python进行功能编程真的对并发有所帮助吗?我只是想了解如果我开始使用Python的更多功能,将会得到什么。 问题答案: 编辑 :由于没有提供更多的解释/示例,我被注释中的任务(部分地,似乎是由FP的狂

  • 以我的拙见,关于“什么是单子”这个著名问题的答案,尤其是投票最多的答案,试图解释什么是单子,而没有明确解释为什么单子是真正必要的。它们能被解释为一个问题的解决方案吗?

  • 问题内容: 该单页应用(SPA)已经到了我们。随之而来的还有很多新功能,例如路由,客户端页面生命周期,MVC模式,MVVM模式,MV *模式等等。还有一些Javascript模式,例如AMD模式,Singleton,Facade,.. 还开发了许多SPA框架和库。我们可以在互联网上找到它的一些内容。它们是AngularJs,Reactjs,BackboneJs,DurandalJs 等等,以及许多