React useContext 不会将值传递给深层嵌套的子级

Posted

技术标签:

【中文标题】React useContext 不会将值传递给深层嵌套的子级【英文标题】:React useContext not passing value down to deeply nested children 【发布时间】:2021-02-03 21:40:52 【问题描述】:

我是 useContext 钩子的新手,并试图找出我做错了什么......没有***导入,这是我的代码的样子:

所以我的项目的根是这样的:

export default function App() 

  return (
    <div className="App">
      <AppProvider>
        <Header/>
        <Toolbar/>
        <Canvas/>
        <Imports/>
        <Footer/>
      </AppProvider>
    </div>
  );

然后我有一个名为 AppProvider 的单独文件,其中包含:

const CanvasItems = createContext();
const UpdateCanvasItems = createContext();

export function useCanvasItems() 
  return useContext(CanvasItems)

export function useChangeItems() 
  return useContext(UpdateCanvasItems)


export default function AppProvider(children) 
  const [state, setState] = useState(
    imports: [],
    images: [],
    text: [],
    circles: [],
    rectangles: [],
    draw: [],
  )

  // function pushes new items in to state object
  function addCanvasItem(type, source) 
    if (type === 'import') 
      const tempState = [...state.imports];
      tempState.push(id: Date.now(), image: source);
      setState(...state, imports: tempState)

     else if (type === 'image') 
      const tempState =  [...state.images];
      tempState.push(
        id: Date.now(),
        src: source.src,
        x: window.innerWidth * Math.random(),
        y: window.innerHeight * Math.random(),
      )
      setState(...state, images: tempState)
    
    console.log("state after new item added:", state)
  

  return (
    <CanvasItems.Provider value=state>
        <UpdateCanvasItems.Provider value=addCanvasItem>
          children
        </UpdateCanvasItems.Provider>
    </CanvasItems.Provider>
  )

我没有任何问题将state 对象和addCanvasItems 函数传递到子级的第一级(因此标题、工具栏、画布等),但我在这些组件中有子级,我可以'不访问值。

为了清楚起见 - 在Canvas 组件内部,我有一个Stage 组件,里面有一个Layer 组件,里面有一个Items 组件(我正在使用Konva 并且需要有所有这些嵌套)。

export default function Canvas() 
  const  onDrop, onDragOver  = useDragDrop;
  const state = useCanvasItems();

  useEffect(() => 
    console.log("state in canvas", state)
  , [state])
  
  return (
      <div id='canvas'>
        <Stage
          container='canvas'
          onDrop=onDrop
          onDragOver=onDragOver
        >
          <Layer>
            <Items/>
          </Layer>
        </Stage>
      </div>
  )

我需要访问Items 组件中的state 对象,但我想避免道具钻孔。为了测试,我创建了一个useEffect 函数来在每次更改时打印状态。 Items 组件在第一次加载时打印undefined,而Canvas 组件打印整个对象。

export default function Items() 
  const state = useCanvasItems();

  useEffect(() => 
    console.log("state in items", state)
  , [state])

  return (
    <>
      state && state.images.map(image => 
          return <NewImage image=image />
      )
    </>
  )
;

what prints to the console on load and after a file is imported (changing the state)

这个钩子我缺少什么以及如何实现它??

非常感谢您的帮助!! ??????????????????

【问题讨论】:

您能在此处的代码框中提供您的代码吗? codesandbox.io 【参考方案1】:

如果您查看Stage 的返回值,它不会呈现children,这意味着图层和项目被视为特殊情况。我认为最好的办法是将道具传递给它们,而不是依赖于上下文,因为它们在技术上似乎根本不是 React 渲染上下文的一部分,而是 Konva 自定义渲染器的一部分:KonvaRenderer

https://github.com/konvajs/react-konva/blob/master/src/ReactKonvaCore.js#L89

  // Stage component
  render() 
    const props = this.props;

    return (
      <div
        ref=(ref) => (this._tagRef = ref)
        accessKey=props.accessKey
        className=props.className
        role=props.role
        style=props.style
        tabIndex=props.tabIndex
        title=props.title
      />
    );
  

文档中有关于如何正确执行此操作的说明:

https://github.com/konvajs/react-konva#usage-with-react-context

由于 React 的一个已知问题,react-konva Stage 组件的子级无法访问上下文。如果您需要从 Stage 内订阅上下文,则需要通过创建一个 Provider 作为 Stage 的子级来“桥接”上下文。有关更多信息,请参阅此讨论和此 react-redux 演示。这是一个桥接上下文的示例(现场演示):

尝试再次将您的提供者添加为 Stage 的子级:

<Stage
  container='canvas'
  onDrop=onDrop
  onDragOver=onDragOver
>
  <CanvasItems.Provider value=state>
    <UpdateCanvasItems.Provider value=addCanvasItem>
      <Layer>
        <Items />
      </Layer>    
    </UpdateCanvasItems.Provider>
  </CanvasItems.Provider>
</Stage>

【讨论】:

以上是关于React useContext 不会将值传递给深层嵌套的子级的主要内容,如果未能解决你的问题,请参考以下文章

在使用数据库数据更新上下文后,React 'useContext' 钩子不会重新渲染

React Context 和 useContext

React.useContext() 不断返回未定义?

使用React useContext hook进行分派调用后,反应状态不会更新

React.useContext 没有更新

使用新的 React 钩子 useContext 的正确方法是啥?