【问题标题】:Strange behavior of React hooks: delayed data updateReact hooks 的奇怪行为:延迟数据更新
【发布时间】:2019-05-04 13:34:02
【问题描述】:

奇怪的行为:我希望第一个和第二个 console.log 显示不同的结果,但它们显示相同的结果,并且只有在下次单击时才会更改值。我应该如何编辑我的代码以使值不同?

function App() {
  const [count, setCount] = React.useState(false);
  const test = () => {
    console.log(count); //false
    setCount(!count);
    console.log(count); //false
  };
  return (
    <div className="App">
      <h1 onClick={test}>Hello StackOverflow</h1>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>

您可以在此处查看一个工作示例: https://codesandbox.io/s/wz9y5lqyzk

【问题讨论】:

  • 注意:请使用 Stack Snippets([&lt;&gt;] 工具栏按钮)将您的可运行示例放在这里,在现场,而不是在场外。 Stack Snippets 支持 React,包括 JSX; here's how to do one.

标签: javascript reactjs react-hooks


【解决方案1】:

状态更新是异步的,因此如果您使用 Hooks,您可以使用 useEffect 在更新后收到通知。

这是一个例子:

https://codesandbox.io/s/wxy342m6l

如果你使用的是 React 组件的 setState,你可以使用回调

this.setState((state) =&gt; ({count: !state.count}), () =&gt; console.log('Updated', this.state.count));

如果您需要状态值,请记住使用回调来更新状态。

【讨论】:

  • 我在 React Native 中有一个编辑表单,起初不包含信息。然后我像你的代码一样调用表单信息。我的问题解决了
【解决方案2】:

State updates are asynchronous。从useState 获得的setCount 函数无法神奇地伸出并更改count 常量的值。一方面,它是一个常数。另一方面,setCount 无权访问它。相反,当您调用 setCount 时,您的组件函数将再次被调用,useState 将返回更新后的计数。

现场示例:

const {useState} = React;

function Example() {
  const [count, setCount] = useState(false);
  const test = () =>{
    setCount(!count); // Schedules asynchronous call to Example, re-rendering the component
  };
  return (
    <div className="App">
      <h1 onClick={test}>Hello CodeSandbox</h1>
      <div>Count: {String(count)}</div>
    </div>
  );
}

ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

如果您需要在count 更改时执行一些副作用,请使用useEffect

useEffect(() => {
  console.log(`count changed to ${count}`);
}, [count]);

请注意,我们告诉 useEffect 仅在 count 更改时调用我们的回调,这样如果我们有其他状态,我们的回调就不会不必要地运行。

现场示例:

const {useState, useEffect} = React;

function Example() {
  const [count, setCount] = useState(false);
  const test = () =>{
    setCount(!count); // Schedules asynchronous call to Example, re-rendering the component
  };
  useEffect(() => {
    console.log(`count changed to ${count}`);
  }, [count]);
  return (
    <div className="App">
      <h1 onClick={test}>Hello CodeSandbox</h1>
      <div>Count: {String(count)}</div>
    </div>
  );
}

ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

【讨论】:

    【解决方案3】:

    setState 钩子不会直接更新组件中的值。它更新其内部状态,导致组件重新渲染,然后返回新的状态值,您将其分配给count

    当您在test 中使用console.log(count) 时,会显示count 的当前值,即旧值(更新前)。如果您将console.log() 移动到渲染中,您将看到新值:

    const { useState } = React;
    
    const Component = () => {
      const [count, setCount] = useState(false);
    
      const test = () => {
        console.log('before: ', count);
        setCount(!count)
      }
      
      console.log('after: ', count);
    
      return (
        <div className="App">
          <button onClick={test}>Click</button>
        </div>
      );
    }
    
    ReactDOM.render(
       <Component />,
       demo
    );
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    
    <div id="demo"></div>

    【讨论】:

      猜你喜欢
      • 2020-01-05
      • 2011-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多