让消费者呈现提供者的目的是啥?

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>
  );

问题是提供给renderProvidercontext 始终是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()),并且您只有一层嵌套。如果你有多个相互嵌套的消费者/提供者对,每个都会注销它从最近的祖先那里得到的东西,而最上面的一个会注销未定义的。你只有最上面的那个。

【讨论】:

感谢您详尽的回答。但我不明白的是,在这种情况下是相同的Contextobject。消费者在Provider 之上呈现,这是我习惯的逆流程(提供者包装消费者)。为什么消费者在这里包装提供者? Why on earth the consumer is wrapping the provider here? 消费者在那里从树上更远的某个地方的提供者那里获取价值。然后提供者在那里为树的其余部分提供修改后的值。如果只有一对这样的对,这是没有用的。关键是要有许多个这样的对,所以当你沿着你遇到的树向下走时:提供者 -> 消费者/提供者 -> 消费者/提供者 -> 消费者/提供者 -> 等等 这个答案很值钱。这是一个***的反应模式。 当然!现在看来如此明显。很好的答案!再次感谢!

以上是关于让消费者呈现提供者的目的是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Kafka 中的 Consumer Id 和 Group Id:是啥让两个消费者相同

dubbo原理和机制是啥?

DDOS攻击是啥

作为开发人员,最好的安卓手机是啥[关闭]

湘橙网超值积分兑换  让消费更过瘾

乱序执行