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

React Context without nesting a provider?

我想知道是否可以创建上下文并使用它而不将上下文传递到 dom 树的整个部分。

为此,我创建了以下示例:

./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
}


并且:./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;

有趣的是,CountDisplayNoProvider 和 CountDisplaySelfProvided 都显示了一个数字:0

但是 count-context.js:34 incrementCount 未定义 count-context.js:35 setCount 是一个未定义的

--- 那么为什么计数被传递给 NO CONTEXT,而不是函数?

更奇怪的是,为什么我不能将提供程序放在计数自己的组件中? (CountDisplaySelfProvided)

谢谢!!

愤怒地点击所有按钮后渲染输出的屏幕截图

前两个 incrementCountButtons 没有工作,因为它无法获取 CountContext.They 现在在 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>

我想我理解为什么那些其他组件确实从上下文中获得了像 0 这样的值。虽然我们确实需要提供者来使用这些值,但其他组件会发生不同的事情。

第一个 CountDisplayNoProvider

这只会消耗您在创建上下文时提供的计数初始值。 const CountContext = React.createContext({count : 0})。但是,如果您尝试使用传递给 Provider 的其他函数,那么它只会 return undefined 因为它在创建上下文时最初没有设置。

CountDisplaySelfProvided

这与第一个 <CountDisplayNoProvider/> 解释了同样的事情。这个问题是你已经在使用 Context 然后在 return.

中提供它

在这种情况下,您在从 供应商。所以你也不能使用这里的功能。当您确实添加了提供者时,useContext 首先运行未定义的函数。

如果它有 children 稍后会通过 useContext 使用它,那么它肯定可以工作并且有自己的计数、setCount 和您提供的所有其他内容。