上下文 API 更新状态导致循环请求

Context API updating state causes looped requests

我有一些背景。我在那里存储用户角色。

const RolesContext = createContext({roles: []});
function RolesContextProvider({children}) {
  const [roles, setRoles] = useState([]);

  async function check(newRoles) {
    const missing = compareArrayWithArray(newRoles, roles);
    if (missing.length !== 0) {
      await User.roles(newRoles).then(((res) => {
        const updatedRoles = roles.concat(res.data);
        setRoles(updatedRoles);
      }));
    }
  }

  const defaultContext = {
    roles,
    check,
  };

  return (
    <RolesContext.Provider value={defaultContext}>
      {children}
    </RolesContext.Provider>
  );
}
export {RolesContext, RolesContextProvider};

启动组件 I 时 运行 检查角色

export default function Users() {
  const UsersComposition = compose(
    connect(mapStateToProps, mapDispatchToProps)
  )(ConnectedUsers);
  const context = useContext(RolesContext);
  const {roles, check} = context;
  useEffect(() => {
    check(['roles', 'to', 'check']);
  }, [check]);
  return <UsersComposition roles={roles}/>;
};

它的作用...应用程序因无限更新状态循环而崩溃。它使用相同的负载发出数十个相同的请求。应该怎么做?感谢您的建议。

您似乎在循环调用 check。看看我说的对不对

  • RolesContextProvider 提供上下文 rolescheck
  • Users 访问上下文并调用 check
  • CheckRolesContextProvider 中的 roles 更新为 setRoles
  • setRolesRolesContextProvider 中触发更新,这会更改上下文
  • 并且上下文更改更新Users
  • 然后循环重复

为了修复无限循环,您需要在渲染之间保留 check 函数的标识。一种方法是使用 useRef 保存它(您需要将现有角色作为第二个参数传递):

const check = useRef(async (newRoles, roles) => {
    ...
});

const defaultContext = {
    roles,
    check: check.current,
};

您也可以考虑将 Users 实现为 class 组件并在 componentDidMount 中调用 check:

class Users extends React.Component {
    static contextType = RolesContext;

    componentDidMount() {
        this.context.check(['roles', 'to', 'check']);
    }

    render() {
        ...
    }
}