【问题标题】:Is this a correct approach to populate the properties of an App Context in React?这是在 React 中填充 App Context 属性的正确方法吗?
【发布时间】:2019-09-23 02:35:51
【问题描述】:

我已经成功地创建了两个上下文,一个用于我在 React 中使用功能组件和 React Hooks 构建的两个不同模块中的每一个。很明显,我将要构建的大多数/所有组件都需要共享数据。我不想对每个顶级组件进行 GET 调用,而是想重构这些公共数据并将其存储在 AppContext 中。这些数据在每个用户的会话中永远不会改变。

起初我尝试将所有填充代码直接放在AppContext 中,但由于上下文尚未初始化,所以没有奏效。于是我创建了一个名为InitAppData 的组件,并像这样将它包装在App.js 中:

<AppContext>
  <Router />
  <InitAppData />
</AppContext>

InitAppData 本身就很标准:

const InitAppData = () => {
  const { appStore,
          updateAppStore } = useContext(AppContext);

  // Populate the AWS Auth Token
  useGetAwsAuthToken();

  // Retrieve the Roles with a GET useFetch call
  const [{ data: rolesData, 
          status: rolesStatus,
          isLoading: rolesIsLoading, 
          isError: rolesIsError }] = useFetch(
    `${API_ROOT()}acct_mgmt/roles`,
    { }
  );

  // Process & populate the fetched Roles
  useEffect(() => {
    if (!rolesIsLoading && rolesStatus === 200) {
      appStore.roles = rolesData.roles;
    }
  }, [rolesIsLoading, rolesStatus]);

  // ... more population to go here ...

    return (null);
}

export default InitAppData;

一切似乎都被正确填充了。我意识到这可能有点不合常规,但它遵循我之前使用的相同模式,即将上下文与组件配对,后者与前者交互。

对大家对这种方法的想法感兴趣。如果有更好的做法,我总是有兴趣学习!

【问题讨论】:

  • 你能提供一些你打算如何做的代码吗?
  • @cbdev420 我刚刚根据您的要求用代码扩展了我的问题。
  • “自我填充”是什么意思?
  • 另外,您能否提供一个如何使用该上下文的示例?
  • 我想我已经回答了我自己的问题。在初始化之前,我似乎无法在 AppContext 中填充任何内容。在AppContext 中,我尝试了几件事来等待这个初始化,但似乎没有一个工作。因此,我认为我将从高级子组件启动人口(@98​​7654330@ 属性)。

标签: reactjs react-hooks react-context


【解决方案1】:

看看这是否有帮助。这就是我一直在做的事情,到目前为止一切正常。

沙盒链接:https://codesandbox.io/s/bold-currying-7fpyw

index.js

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router } from "react-router-dom";
import AppContext from "./AppContext";
import AllRoutes from "./AllRoutes";

function mockAPI() {
  return new Promise((resolve, reject) =>
    setTimeout(
      () =>
        resolve({
          propA: "This is some propA value",
          propB: "This is some propB value"
        }),
      1500
    )
  );
}

function App() {
  const [appState, setAppState] = useState(null);
  const [loading, setLoading] = useState(true);

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

  async function callMockAPI() {
    const response = await mockAPI();
    setAppState(response);
    setLoading(false);
  }

  return (
    <AppContext.Provider value={appState}>
      {loading ? (
        <div>I am waiting for the API to respond...</div>
      ) : (
        <Router>
          <AllRoutes />
        </Router>
      )}
    </AppContext.Provider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

AppContext.js

import React from "react";

const AppContext = React.createContext(null);

export default AppContext;

AllRoutes.js

import React from "react";
import { Route, Switch } from "react-router-dom";
import Home from "./Home";
import SomeComponent from "./SomeComponent";

function AllRoutes() {
  return (
    <Switch>
      <Route exact path="/" component={Home} />
      <Route exact path="/someComp" component={SomeComponent} />
    </Switch>
  );
}

export default AllRoutes;

结果:

【讨论】:

  • 谢谢你。一个问题:假设您的应用程序必须在callMockAPI 运行之前登录或在登录后第二次运行。它会正确处理这个问题吗?
  • 我刚刚意识到我不能完全按照你的方式去做,因为我团队的 App.js 目前是一个类组件。我们正在过渡到拥有所有功能组件。
  • 我相信你可以像我一样使用Context.Provider。对于useEffect,您可以使用componentDidMount
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-19
  • 2013-10-03
  • 2015-03-15
  • 2013-09-25
  • 1970-01-01
相关资源
最近更新 更多