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' 钩子不会重新渲染