让消费者呈现提供者的目的是啥?
Posted
技术标签:
【中文标题】让消费者呈现提供者的目的是啥?【英文标题】:What is the purpose of having a consumer rendering a provider?让消费者呈现提供者的目的是什么? 【发布时间】:2020-04-05 20:08:27 【问题描述】:我在查看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>
Source
这让我很困惑,起初我认为这是一种无需太多努力即可访问先前上下文的递归方式。但我试图在这样的沙箱中重现它
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>
);
问题是提供给renderProvider
的context
始终是undefined
。
这种特定模式的目的是什么?我在这里错过了什么?
【问题讨论】:
没完全看懂,推荐你看看JssProvider.test.js 尽管如此,还是让我大吃一惊 但是您甚至没有在 renderProvider 函数中使用context
参数..
只是记录它。
【参考方案1】:
当组件树中有多个相同的提供者时,它们会相互“影子”,类似于同名变量shadow相互之间的方式。任何时候你渲染一个消费者,它只会看到树上最近的提供者的值。
所以他们在这里所做的就是利用这一点。提供者存在于树的顶部附近,并为其后代提供值。其中一个后代侦听该值,但随后立即制作该值的修改版本并提供它。因此,低于第二个提供者的任何东西都只能看到修改后的值,而不是原始值。
我不确定他们在代码中使用它的目的是什么,但我之前已经将它用于几件事:
1) 仅针对某个部分覆盖页面的主题。
我们在应用顶部有一个主题提供程序,它指定用于样式的常量。但是在树中间的某个地方是一个组件,它将读取该全局主题,覆盖一些值,然后将修改后的主题提供给它的后代。那些后代只能访问修改后的主题。
在我们的例子中,这让我们可以预览主题在全局应用时的样子。
2) 用于聚合关于我们的组件树的元数据。
我们有一个用例,其中组件需要知道它们正在使用的应用程序的区域,因此我们在树顶部附近设置了一个提供程序,它提供了一个值,基本上是 page: 'Login'
(或任何)。下面是一个消费者/提供者对,它将接受并添加到它,提供page: 'Login', section: 'Credentials'
。然后低于它再次将其增强为page: 'login', section: 'Credentials', subsection: 'email'
。
最后,任何只使用上下文(不提供自己的值)的组件都可以知道它在应用程序中的位置。它只会从最近的祖先那里获取值,因此它的信息量恰到好处。
问题是提供给renderProvider的上下文总是未定义的。
您看到未定义的原因是这是您创建的上下文的默认值(因为您没有将任何内容传递给React.CreateContext()
),并且您只有一层嵌套。如果你有多个相互嵌套的消费者/提供者对,每个都会注销它从最近的祖先那里得到的东西,而最上面的一个会注销未定义的。你只有最上面的那个。
【讨论】:
感谢您详尽的回答。但我不明白的是,在这种情况下是相同的Context
object。消费者在Provider
之上呈现,这是我习惯的逆流程(提供者包装消费者)。为什么消费者在这里包装提供者?
Why on earth the consumer is wrapping the provider here?
消费者在那里从树上更远的某个地方的提供者那里获取价值。然后提供者在那里为树的其余部分提供修改后的值。如果只有一对这样的对,这是没有用的。关键是要有许多个这样的对,所以当你沿着你遇到的树向下走时:提供者 -> 消费者/提供者 -> 消费者/提供者 -> 消费者/提供者 -> 等等
这个答案很值钱。这是一个***的反应模式。
当然!现在看来如此明显。很好的答案!再次感谢!以上是关于让消费者呈现提供者的目的是啥?的主要内容,如果未能解决你的问题,请参考以下文章