【问题标题】:React.useState re-renders with wrong stateReact.useState 以错误的状态重新渲染
【发布时间】:2020-04-11 03:14:58
【问题描述】:

我有以下控制我的仪表板的精简代码

function App(props){
    const [role, setRole] = React.useState("guest");
    const [componentDrawerRender, setComponentDrawerRender] = React.useState(null);

    const handleSelectionDrawerClick = (component) => {

        setComponentDrawerRender(component);
        handleOpenComponentDrawer(true);
    };

    const handleLoginCallback = (user) => {

        if (user !== false) {
          handleCloseComponentDrawer();
          setRole(user.type);    <-- setting the new state does not work 
          console.log(val.type + " -> " + role );   <-- this here shows != values

        } else {
          //do nothing
        }
      };

    return (  
        <Button
        onClick={() => {
          handleSelectionDrawerClick(
            <LoginPage callback={handleLoginCallback} />
          );
        }}
      >
        LOG IN
      </Button>);
}

这段代码的目的是打开一个抽屉(它会这样做),在抽屉中渲染一个组件(它会这样做),并且在用户使用组件登录后关闭抽屉(它会这样做)并更新状态(几乎就是这样)。

问题发生在handleLoginCallback 方法中。好的数据被发回,状态用好的数据更新。然而,只有页面上的一些组件被更新。

功能组件的重新渲染过程如何工作?它只是再次调用该函数还是仅以某种方式重新计算返回值?以下代码不会在重新渲染时重新计算。让某些状态依赖于其他状态可以吗?

const [mainList, setMainList] = React.useState((role) => {
    console.log(role);
    if (role === undefined || role === null) {
      return GuestListItems(handleSelectionDrawerClick);
    } else if (role === "customer") {
      return CustomerListItems;
    } else {
      return OwnerListItems;
    }
  });

下面是&lt;LoginPage&gt; 中调用回调方法的代码。

onSubmit(e) {
    e.preventDefault();

    this.setState({ isLoading: true });
    this.props.login(this.state, this.handleLoadingBar).then((retState) => {
      if(retState === null){
        this.props.callback(false);       <-- here 
      }else {
        this.props.callback(retState);    <-- here 
      }
    });
  }

【问题讨论】:

    标签: reactjs react-functional-component use-state


    【解决方案1】:

    在您的代码中,role 值会在后续刷新(即函数调用)时更新,因为 setRole 调用。有几个原因,因为console.log 行的角色没有改变:

    1. role 被标记为 const;
    2. JavaScript 在当前函数完成之前不会运行任何其他函数(更好的是:调用堆栈变空)。

    也检查一下:https://reactjs.org/docs/hooks-reference.html#functional-updates

    useState 钩子是一个普通函数,它获取一个参数并返回一个元组。尽管每次刷新都会调用钩子(以及参数),但参数值仅在第一次初始化时使用。

    API 说明如下:https://reactjs.org/docs/hooks-reference.html#usestate

    【讨论】:

    • 为什么状态没有为他们更新mainList呢?
    • 你的意思是mainList const 没有在第一遍初始化?老实说,我不明白你关于 2nd sn-p 的问题。
    【解决方案2】:
    onSubmit(e) {
        e.preventDefault();
    
        this.setState({ isLoading: true });
        this.props.login(this.state, this.handleLoadingBar).then((retState) => {
          if(retState === null){
            this.props.callback(false);       <-- here 
          }else {
            this.props.callback(retState);    <-- here 
          }
        });
      }
    

    您将 this 的初始状态设置为函数,而不是函数的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-01
      • 2018-10-03
      • 1970-01-01
      • 2019-11-09
      • 1970-01-01
      • 2019-07-18
      • 1970-01-01
      • 2016-11-04
      相关资源
      最近更新 更多