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

Posted

技术标签:

【中文标题】在不嵌套提供者的情况下反应上下文?【英文标题】:React Context without nesting a provider? 【发布时间】:2021-07-04 07:33:32 【问题描述】:

我想知道是否可以创建一个上下文并使用它而不将上下文传递到 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)

谢谢!!

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

【问题讨论】:

【参考方案1】:

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

First CountDisplayNoProvider

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

CountDisplaySelfProvided

这与第一个&lt;CountDisplayNoProvider/&gt; 解释了同样的事情。这个问题是你已经在使用 Context 然后在返回中提供它。

在这种情况下,您在从 提供者。所以你也不能在这里使用这些功能。虽然您确实添加了提供程序,但 useContext 首先运行未定义的函数。

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

【讨论】:

【参考方案2】:

前两个 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>

【讨论】:

以上是关于在不嵌套提供者的情况下反应上下文?的主要内容,如果未能解决你的问题,请参考以下文章

z-index和嵌套DOM元素(堆叠上下文)覆盖

MSVC 在不知道类型的情况下评估上下文(和错误)

通过反应上下文 api 将子状态传递给父组件

在不禁用上下文菜单的情况下管理 UITextfiled 上的长按?

在不修改实体类(注释)或数据上下文(使用 fluentapi)的情况下禁用标识(自动递增)

是否可以在不重新加载页面的情况下更新 django 上下文字典?