无法通过在函数中使用 useState 获取第一个值

Can't get the first value by using useState in a functionn

我需要根据数据值显示文本。通过 运行 代码,我想看到 'Test1: 1' 在我点击按钮后可以显示,但我不能。有什么方法可以做到这一点?

下面是包含代码的示例沙箱 link。 https://codesandbox.io/s/restless-wildflower-9pl09k?file=/src/Parent.js

export default function Parent(props) {
  const [data, setData] = useState(0);
  const onClick = () => {
    setData(1);
    console.log(data);
    setData(2);
  };
  return (
    <>
      <button onClick={onClick}> Click here </button>
      {data === 1 ? <div>Test1: {data}</div> : <div>Test2: {data}</div>}
    </>
  );
}

console.log(data) 没有反映最新数据的原因是 React 管理状态。调用 setState() 是异步的,如果你想依赖状态的新值,正确的方法是传递一个旧状态的函数,返回当前状态。 ref. documentation

useState返回的setState函数不直接更新状态。相反,它用于发送 React 将在下一次异步状态更新期间使用的值。 console.log 是一个效果,所以如果你想在每次更改时看到 data 记录,你可以使用 React.useEffect运行下面的代码,点击0按钮几次,在浏览器中查看状态变化和效果。

function App() {
  const [data, setData] = React.useState(0)
  React.useEffect(_ => console.log("data", data), [data])
  return <button
    onClick={_ => setData(data + 1)}
    children={data}
  />
}

ReactDOM.render(<App/>, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

您的评论谈到了网络请求示例。可以设计自定义挂钩以适应复杂的用例并使您的组件易于编写。

function App() {
  const [{fetching, error, data}, retry] = useAsync(_ => {
    return fetch("https://random-data-api.com/api/users/random_user")
      .then(res => res.json())
  }, [])
  if (fetching) return <pre>Loading...</pre>
  if (error) return <pre>Error: {error.message}</pre>
  return <div>
    <button onClick={retry} children="retry" />
    <pre>{JSON.stringify(data, null, 2)}</pre>
  </div>
}

function useAsync(f, deps) {
  const [state, setState] = React.useState({fetching: true})
  const [ts, setTs] = React.useState(Date.now())
  React.useEffect(_ => {
    f()
      .then(data => setState({fetching: false, data}))
      .catch(error => setState({fetching: false, error}))
  }, [...deps, ts])
  return [
    state,
    _ => {
      setState({fetching: true, error: null, data: null})
      setTs(Date.now())
    }
  ]
}

ReactDOM.render(<App/>, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>