当我在其主要提供程序中遇到以下代码时,我正在看react-jss
的源代码,这些代码称为JssProvider
renderProvider = (parentContext: Context) => {
const {children} = this.props
const context: Context = this.createContext(parentContext, this.prevContext)
this.prevContext = context
return <JssContext.Provider value={context}>{children}</JssContext.Provider>
}
render() {
return <JssContext.Consumer>{this.renderProvider}</JssContext.Consumer>
}
}
这让我很困惑,起初我认为这是一种无需过多努力即可访问先前上下文的递归方法。但是我试图在这样的沙盒中重现它
const context = React.createContext();
const { Provider, Consumer } = context;
const FooProvider = ({ children }) => {
const [state, setState] = React.useState({
value: "foo",
setValue: value => setState(p => ({ ...p, value }))
});
const renderProvider = context => {
console.log(context);
return <Provider value={state}>{children}</Provider>;
};
return <Consumer>{renderProvider}</Consumer>;
};
function App() {
const onClick = setter => {
setter("bar");
};
return (
<FooProvider>
<Consumer>
{context => (
<div>
{context.value}
<button onClick={() => onClick(context.setValue)}>Change</button>
</div>
)}
</Consumer>
</FooProvider>
);
}
问题是提供给context
的{{1}}始终是renderProvider
。
此特定模式的目的是什么?我在这里想念什么?
答案 0 :(得分:3)
当组件树中有多个相同的提供程序时,它们将彼此“阴影化”,其方式类似于具有相同名称shadow的变量彼此之间的方式。每次渲染消费者时,它只会从树上最近的提供者那里看到值。
因此,他们在这里所做的就是利用这一点。提供程序存在于树的顶部附近,并为其后代提供值。这些后代之一侦听该值,然后立即制作该值的修改版本并提供它。因此,低于此第二个提供程序的任何内容都将只能看到修改后的值,而看不到原始值。
我不确定他们在代码中使用了什么,但是我以前在一些方面使用了它:
1)用于仅覆盖特定部分的页面主题。
我们的应用程序顶部将有一个主题提供程序,用于指定用于样式的常量。但是,在树中间的某个地方是一个组件,它将读取该全局主题,覆盖一些值,然后向其后代提供经过修改的主题。这些后代只能访问修改后的主题。
在我们的案例中,这使我们可以预览主题在全局应用时的外观。
2)用于汇总有关组件树的元数据。
我们有一个用例,其中的组件需要知道它们在其中使用的应用程序的区域,因此我们在树的顶部附近的位置设置了一个提供程序,提供了一个基本为{page: 'Login'}
的值。 (管他呢)。在其下方的是一对消费者/提供者,它将接受并添加到其中,提供{page: 'Login', section: 'Credentials'}
。然后是将其再次增加到{page: 'login', section: 'Credentials', subsection: 'email'}
的那个。
最后,任何只消耗上下文(不提供其自身值)的组件都可以知道它在应用程序中的位置。它只会从最接近的祖先那里获得价值,因此它只具有正确的信息量。
问题在于提供给renderProvider的上下文始终未定义。
您看到未定义的原因是这是您创建的上下文的默认值(因为您没有向React.CreateContext()
传递任何内容),并且您只有一层嵌套。如果您有多个这样的消费者/提供者对彼此嵌套,则每个都会从最近的祖先注销,而最上面的则注销未定义。您只有最顶层的那个。