umijs / hox

State sharing for React components.

Home Page:https://hox.js.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

model中不能使用useEffect进行一些异步请求操作吗,报错了

coopercoder opened this issue · comments

import { createModel } from 'hox';
import { useState, useEffect } from 'react';
import { usePersistFn } from '@umijs/hooks';
import { queryCurrent } from '@/services/user';
import useTokenModel from '@/models/useToken';

const defaultUserInfo = {
  userId: null,
  userName: null,
  avatar: null,
};

function useUserInfo() {
  const [access, setAccess] = useState({});
  const [userInfo, setUserInfo] = useState({ ...defaultUserInfo });
  const [userInfoLoaded, setUserInfoLoaded] = useState(false);
  const { token } = useTokenModel((model) => [model.token]);

  const resetUserInfo = usePersistFn(() => {
    setAccess({});
    setUserInfo({ ...defaultUserInfo });
    setUserInfoLoaded(false);
  });

  const loadUserInfo = usePersistFn(() => {
    queryCurrent().then((res) => {
      if (res?.code === 0) {
        const { userInfo: ui, accessList = [] } = res.result;
        const newAccessListObj = {};
        accessList.forEach((element) => {
          newAccessListObj[element] = true;
        });
        setAccess(newAccessListObj);
        setUserInfo({ ...ui });
        setUserInfoLoaded(true);
      }
    });
  });

  useEffect(() => {
    if (token === null) {
      resetUserInfo();
    } else {
      loadUserInfo();
    }
  }, [token]);

  return {
    access,
    userInfo,
    userInfoLoaded,
  };
}

export default createModel(useUserInfo);

报错信息如下:

Warning: Cannot update a component (`Executor`) while rendering a different component (`Executor`). To locate the bad setState() call inside `Executor`, follow the stack trace as described in https://fb.me/setstate-in-render
    in Executor

具体报错是在执行

setAccess(newAccessListObj);
setUserInfo({ ...ui });
setUserInfoLoaded(true);

不知道为何啊

same

异步这块,是不是得考虑 recoil 了?recoil 专门的API处理 async await ,但是切换到recoil,这样的写法就有点 累赘~

const a1 = Atom("something");

const selecta1 = selector(){
     dosomething
}

function useAccess( ){
     const [a, setA] = useRecoilState(a1);
     const update = setA("something new");
     return {a,update}
}

可以在useEffect里面使用闭包进行异步操作吧

   useEffect(() => {
        (async () => {
            await xxxx()
        })()
    }, [])

20d37bc 中增加了异步状态更新的测试用例,并没有复现出这个 warning,先 close 了哈