我正在尝试使用React上下文api在我的应用程序中实现共享状态。
我正在树的根部创建一个errorContext
状态。错误上下文如下所示:
// ErrorContext.js
import React from 'react';
const ErrorContext = React.createContext({
isError: false,
setError: (error) => {}
});
export default ErrorContext;
辅助功能的用法示例
http.get('/blah')
.catch((error) => {
HelperLibrary.setError(true);
})
我可以像这样创建提供者:
class ProviderClass {
state = {
isError: false,
setError: (error) => {
this.state.isError = error;
}
}
render() {
return (
<ErrorContext.Provider value={this.state}>
{this.props.children}
</ErrorContext.Provider>
)
}
}
然后我可以通过在render调用中使用Consumer包装器来使用此提供程序:
<ErrorContext.Consumer>
{(context) => {
context.setError(true);
}}
</ErrorContext.Consumer>
这种方法要求我们团队中的每个开发人员每次希望处理Web服务错误时都要编写许多样板代码。
例如他们必须将ErrorContext.Consumer
放置在组件render()
方法内,并根据Web服务响应有条件地进行渲染。
在帮助器函数中使用ReactDOM.render。
const setError = (error) =>{
ReactDOM.render(
<ErrorContext.Consumer>
// boilerplate that i mentioned above
</ErrorContext.Consumer>,
document.getElementById('contextNodeInDOM')
) }
export default setError;
为什么这行不通?
由于某种原因,ReactDOM.render()始终将此代码放置在React组件树之外。
<App>
...
<ProviderClass>
...
<div id="contextNodeInDOM'></div> <-- even though my node is here
...
</ProviderClass>
</App>
<ErrorContext.Consumer></ErrorContext.Consumer> <-- ReactDOM.render puts the content here
因此,没有为使用者找到上下文父级,因此它默认为默认上下文(无状态)
从docs
如果上面没有此上下文的提供者,则使用value参数 将等于传递给createContext()的defaultValue。
如果有人可以帮助我进行下一步,那么我会从Angular来,如果我的术语不正确或者我做的非常愚蠢,我深表歉意。
答案 0 :(得分:3)
您可以导出HOC以在导出之前包装错误组件,从而消除样板并确保仅在需要的地方提供上下文,而不会与DOM混淆:
// error_context.js(x)
export const withErrorContext = (Component) => {
return (props) => (
<ErrorContext.Consumer>
{context => <Component {...props} errorContext={context} />}
</ErrorContext.Consumer>
)
};
// some_component.js(x)
const SomeComponent = ({ errorContext, ...props }) => {
http.get('/blah')
.catch((error) => {
errorContext.setError(true);
})
return(
<div></div>
)
};
export default withErrorContext(SomeComponent);
现在,React 16.8降落了,您还可以使用钩子更干净地执行此操作:
const SomeComponent = props => {
const { setError } = useContext(ErrorContext)
http.get("/blah").catch(() => setError(true))
return <div />
}
答案 1 :(得分:0)
跟随react上下文文档:
我可以像这样创建提供者:
class ProviderClass { state = { isError: false, setError: (error) => { this.state.isError = error; } }
我不这么认为-应该使用setState
。反应中有一个通用规则“ 不要改变状态-使用setState()”-滥用会引起很大的反应问题。
我觉得您不了解上下文角色/用法。这更像是通向全球商店的捷径,无需通过深层组件结构将道具显式地传递给孩子(有时更多)。超过10个级别。
App> CtxProvider >路由器>其他> ..> CtxConsumer> ComponentConsumingCtxStorePropsNMethods
在某些特殊情况下使用访问具有ID的渲染DOM节点,通常应避免,因为后续渲染会破坏外部所做的任何更改。
如果您需要在主要React应用html节点之外的某个地方渲染某物,请使用portals。