使用 Context API 设置 React 应用程序的最佳方法是什么,这将允许我为应用程序的每个路由提供一些全局状态和方法?
示例:我想在应用程序的顶层处理 REST 和 Auth,所以我希望我的组件在顶层调用请求方法并将响应数据过滤器返回到组件级别。
而且……这种架构在 React 范式中是否有效?(我是 React 新手)
使用 Context API 设置 React 应用程序的最佳方法是什么,这将允许我为应用程序的每个路由提供一些全局状态和方法?
示例:我想在应用程序的顶层处理 REST 和 Auth,所以我希望我的组件在顶层调用请求方法并将响应数据过滤器返回到组件级别。
而且……这种架构在 React 范式中是否有效?(我是 React 新手)
您将 Context 中的函数注入到容器道具中: https ://reactjs.org/docs/context.html#accessing-context-in-lifecycle-methods
如果你愿意,你也可以在没有上下文的情况下这样做,看起来像:
<Router>
<Switch>
<Route path='/' render={props => <Container {...props} API={API} />} />
TLDR;CodeSandbox 演示
好的,经过一些工作,我找到了解决问题的方法(我是 React 新手),所以也许这是一个愚蠢的解决方案。如果是这样.. 提供更好的答案,我很乐意接受您的回答。
解决方案
使用Unstated 库,我可以围绕提供依赖注入的 React Context API 创建一个包装器。这允许我实例化可以传递给我的组件的实例。
例如:
import { Provider, Subscribe } from "unstated";
import CounterContainer from "./counter";
let counterA = new CounterContainer({ initAmount: 4 });
let counterB = new CounterContainer({ initAmount: 8 });
const Red = () => {
return (
<Subscribe to={[CounterContainer]}>
{counter => (
<div className="red">
<span>{counter.state.count}</span>
...
</div>
)}
</Subscribe>
);
};
const App = () => (
<div>
<Provider inject={[counterA]}>
<Red />
</Provider>
<hr />
<Provider inject={[counterB]}>
<Red />
</Provider>
</div>
);
在 CodeSandbox 上试用演示:https ://codesandbox.io/s/k3v3wnzrn7
我扩展了这个想法,创建了一个框架 API 服务。API 服务包含状态属性,例如loggedIn
,以及服务方法,例如login()
和logout()
。这些属性和方法在整个应用程序中都可用,只需在我想使用 API 服务的每个地方进行一次导入。
我通过在Api.js
服务中包装未说明的提供者、订阅和实例来做到这一点。
例如:
api.js:
import { Provider, Subscribe, Container } from "unstated";
class APIContainer extends Container {
constructor(props = {}) {
super();
this.state = {
loggedIn: false
};
}
async login() {
console.log("Logging in");
this.setState({ loggedIn: true });
}
async logout() {
console.log("Logging out");
this.setState({ loggedIn: false });
}
}
const Api = {
Instance: new APIContainer(),
Provider,
Subscribe
};
export default Api;
现在我可以将Api.js
它作为提供者包含在任何其他文件中,注入我关心的实例。在这种情况下,只有一次实例,但如果我想运行并行测试,我可以提供不同的实例。
应用程序.js:
import Api from "./Api";
class App extends React.Component {
render() {
return (
<div>
<Api.Provider inject={[Api.Instance]}>
<Routes />
</Api.Provider>
</div>
);
}
}
render(<App />, document.getElementById("root"));
然后我可以在Api.js
整个应用程序中包含,并订阅从树中传递的任何实例。
页面/Foo.js:
import Api from "../Api";
class Foo extends React.Component {
render() {
return (
<Api.Subscribe to={[Api.Instance]}>
{api => (
<div>
<h1> Foo</h1>
<pre>
api.state.loggedIn = {api.state.loggedIn ? " true" : " false"}
</pre>
<button onClick={() => api.login()}>Login</button>
<button onClick={() => api.logout()}>Logout</button>
</div>
)}
</Api.Subscribe>
);
}
}
export default Foo;
在此处尝试 CodeSandbox 演示:https ://codesandbox.io/s/wqpr1o6w15
也许一个更有经验的 React 开发者可以插话我是否无缘无故地扼杀了 React 框架)......