简体   繁体   English

在不嵌套提供者的情况下反应上下文?

[英]React Context without nesting a provider?

I'm wondering if it's possible to create a context and consume it without passing the context down the whole section of the dom tree.我想知道是否可以创建一个上下文并使用它而不将上下文传递到 dom 树的整个部分。

To that extent I've created the following example:在这种情况下,我创建了以下示例:

./components/count-context.js

import * as React from 'react'
const CountContext = React.createContext({count : 0} )


const CountContextProvider = (props) => {
  const [count, setCount] = React.useState(0);
  
  const incrementCount = () => {
    console.log("increment count", count)
    setCount(count + 1);
  };

  const decrementCount = () => {
    setCount(count - 1);
  }

  return (
    <CountContext.Provider value={{ count, setCount, incrementCount, decrementCount }}>
      {props.children}
    </CountContext.Provider>
  );
}

const CountDisplayNoProvider = (props) => {
  const { count } = React.useContext(CountContext)
  return (
      <p>{count}</p>
  )
}

const CountDisplaySelfProvided = (props) => {
  const { count } = React.useContext(CountContext)
  return (
    <CountContextProvider>
      <p>{count}</p>
    </CountContextProvider>
  )
}

const IncrementCountButton = (props) => {
  const { count, incrementCount, setCount } = React.useContext(CountContext)
  console.log(`count is a `, typeof(count))
  console.log(`incrementCount is a `, typeof(incrementCount))
  console.log(`setCount is a `, typeof(setCount))
  return (
    <button onClick={incrementCount}>IncrementCountButton</button>
  )
}
 

export {
  CountContextProvider,
  CountDisplayNoProvider,
  CountDisplaySelfProvided,
  IncrementCountButton
}


And: ./App.js并且: ./App.js

import './App.css';

import { CountContextProvider, CountDisplaySelfProvided, CountDisplayNoProvider, IncrementCountButton} from './components/count-context'

function App() {

  return (
    <div className="App">
      <p>NO CONTEXT</p>
        CountDisplayNoProvider: <CountDisplayNoProvider />
        <IncrementCountButton />

        <br />

        CountDisplaySelfProvided: <CountDisplaySelfProvided />
        <IncrementCountButton />

      <CountContextProvider>
        <p>CountDisplayNoProvider inside CountContextProvider</p>
        <CountDisplayNoProvider />
        <IncrementCountButton />
      </CountContextProvider>
    </div>
  );
}

export default App;

The funny thing is that the CountDisplayNoProvider and CountDisplaySelfProvided both show a number: 0有趣的是 CountDisplayNoProvider 和 CountDisplaySelfProvided 都显示一个数字:0

but count-context.js:34 incrementCount is a undefined count-context.js:35 setCount is a undefined但是 count-context.js:34 incrementCount 是未定义的 count-context.js:35 setCount 是未定义的

--- so why is it that the count gets passed to NO CONTEXT, but not the functions? --- 那么为什么计数被传递给 NO CONTEXT,而不是函数?

And even stranger, why is it that I can't put the provider in the count's own component?更奇怪的是,为什么我不能将提供者放在 count 自己的组件中? ( CountDisplaySelfProvided ) ( CountDisplaySelfProvided )

Thank you!!谢谢!!

Screenshot of the rendered output after rage clicking all the buttons愤怒点击所有按钮后渲染的 output 的屏幕截图愤怒点击所有屁股后渲染输出的屏幕截图

The first two incrementCountButtons did not work as it can not get CountContext.They are outside CountContextProvider now, you probably want to move it inside the CounterContextCounter前两个 incrementCountButtons 不起作用,因为它无法获取 CountContext。它们现在位于 CountContextProvider 之外,您可能希望将其移动到 CounterContextCounter 内

<div className="App">
    <CountContextProvider>    // Move CounterContextProvider here
      <p>NO CONTEXT</p>
        CountDisplayNoProvider: <CountDisplayNoProvider />
        <IncrementCountButton />
        <br />
        CountDisplaySelfProvided: <CountDisplaySelfProvided />
        <IncrementCountButton />
        <p>CountDisplayNoProvider inside CountContextProvider</p>
        <CountDisplayNoProvider />
        <IncrementCountButton />
    </CountContextProvider>    // end of counter context provider
 </div>

I think I understand as to why those other components did get some value like 0 from the context.我想我理解为什么那些其他组件确实从上下文中获得了像 0 这样的值。 While we do need the provider to consume the values, different things happen to the other components.虽然我们确实需要提供者来使用这些值,但其他组件会发生不同的事情。

First CountDisplayNoProvider第一个 CountDisplayNoProvider

This only consumes the initial value of count which you've provided when creating the Context.这只会消耗您在创建 Context 时提供的 count 的初始值。 const CountContext = React.createContext({count: 0}) . const CountContext = React.createContext({count: 0}) However, if you've tried consuming the other functions you've passed on the Provider, then it would only return undefined because of it not being set initially when the context was created.但是,如果您尝试使用在 Provider 上传递的其他函数,那么它只会返回 undefined,因为在创建上下文时最初没有设置它。

CountDisplaySelfProvided CountDisplaySelfProvided

This explains the same thing with the First <CountDisplayNoProvider/> .这与 First <CountDisplayNoProvider/>解释了同样的事情。 The problem with this one is you're already using the Context then providing it inside the return.这个问题是您已经在使用 Context 然后在返回中提供它。

In this case, you're consuming it before you get everything from the Provider.在这种情况下,您在从 Provider 获取所有内容之前就已使用它。 So you wouldn't be able to use the functions here too.所以你也不能在这里使用这些功能。 While you did add a Provider, useContext runs first thus the undefined functions.虽然您确实添加了提供程序, useContext首先运行,因此未定义的函数。

If it had children who would later consume it via useContext, then it should definitely work and have their own count, setCount & everything else you've provided.如果它有孩子以后会通过 useContext 使用它,那么它肯定可以工作并且有自己的计数、setCount 和您提供的所有其他内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM