【问题标题】:React useContext not passing value down to deeply nested childrenReact useContext 不会将值传递给深层嵌套的子级
【发布时间】: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

标签: javascript reactjs react-props use-context


【解决方案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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    • 2019-12-10
    • 2017-08-23
    • 1970-01-01
    • 2019-03-18
    相关资源
    最近更新 更多