React useState 钩子不在异步 useEffect 中更新

React useState hook not updating within async useEffect

我想用我保存在 localStorage 中的对象覆盖 user,但它不起作用。

注意,组件被称为 Index 因为我正在使用 next.js

import React, { useState, useEffect } from 'react';
import { loadUser } from '../utils/user';

const Index = () => {
  const [ user, setUser ] = useState({});

  async function restore(){
    const loadedUser = await loadUser();
    console.log(loadedUser);                    // correct - {userId: 4124783261364}
    setUser(loadedUser); 
    console.log(user);                          // was not updated - {}
  };

  useEffect(() => {
    restore();
  }, [0])

  return (<></>);
};

export default Index;

尝试这样的事情:

// Assuming your loadUser() functions is set like the line below
const loadedUser = {userID: '513216351354'};


const Index = () => {

function restore(){
  console.log("Loaded user is " + loadedUser.userID);       // Loaded user is 513216351354
  setUser(loadedUser.userID); 
  console.log("User is " + user);                          // User is 513216351354
};

useEffect(() => {
  restore();
}, [])

return (<></>);
}

export default Index;

问题

  • 如果你想运行一个效果并清理它只一次(在mountunmount),可以传一个空数组([]) (不是[0]) ,作为第二个参数。这告诉 React 你的效果 不依赖于 props 或 state 的任何值,所以它 never 需要 re-run.
  • 很像Class组件中的setState通过扩展React.Component或React.PureComponent创建的,状态更新使用[=提供的updater 26=]useState hook也是异步的,不会立即体现。这就是 为什么 console.log(user); 没有在 setUser(loadedUser);
  • 旁边显示更新值

解决方案

  const restore = async () => {
    const loadedUser = await loadUser();
    console.log(loadedUser);                    // correct - {userId: 4124783261364}
    setUser(loadedUser); 
    console.log(user);                          // user is not updated here, but will be
  };

  useEffect(() => {
    restore();
  }, []);

类似情况

远离您的问题,因为您只需要一次从本地存储加载用户。但是当loadUser() returns 改变结果需要实时更新用户时,你应该使用useCallback.

  const updateUser = useCallback(async () => {
    const loadedUser = await loadUser();
    setUser(loadedUser); 
  }, []);

  useEffect(() => {
    updateUser();
  }, [updateUser]);