React中如何向孙组件传递Props?当前实现出现undefined问题
解决React中无需Prop Drilling传递name属性给深层组件的问题
问题分析
你当前的实现有两个核心问题导致MyComponent无法拿到name值:
- ParentComponent的子元素处理逻辑错误:遍历外层
ChildComponent后,直接返回了内层MyComponent的克隆结果,相当于丢弃了原有的ChildComponent层级,导致组件结构混乱,属性传递路径断裂。 - 示例代码结构语法错误:第二个
ChildComponent的闭合标签写法错误,应该是<ChildComponent><MyComponent /></ChildComponent>,而非拆分的闭合标签。
方案一:修正cloneElement逻辑(保留组件层级)
调整ParentComponent的实现,正确克隆ChildComponent并替换它的子元素,确保层级结构完整的同时传递属性:
import { ReactElement, Children, cloneElement, isValidElement } from 'react'; const ParentComponent = ({ children }: { children: React.ReactNode }) => { return Children.map(children, (child, childIndex) => { // 跳过非React元素类型的子节点 if (!isValidElement(child)) return child; // 遍历ChildComponent的子元素,为MyComponent添加name属性 const updatedInnerChildren = Children.map(child.props.children, (innerChild, innerIndex) => { if (!isValidElement(innerChild)) return innerChild; return cloneElement(innerChild as ReactElement, { name: `${childIndex}-${innerIndex}-name`, }); }); // 克隆原ChildComponent,替换它的子元素为更新后的内容 return cloneElement(child as ReactElement, { children: updatedInnerChildren, }); }); };
修正后的组件结构:
<ParentComponent name="name"> <ChildComponent> <MyComponent /> </ChildComponent> <ChildComponent> <MyComponent /> </ChildComponent> </ParentComponent>
方案二:使用React Context(推荐,彻底避免Prop Drilling)
如果你的组件层级更深或需要跨多个层级传递数据,React Context是更优雅的解决方案:
1. 创建Context
// NameContext.tsx import { createContext, useContext } from 'react'; type NameContextType = string | undefined; const NameContext = createContext<NameContextType>(undefined); export const NameProvider = NameContext.Provider; export const useName = () => useContext(NameContext);
2. 在ParentComponent中提供Context值
import { NameProvider, isValidElement, Children, cloneElement } from 'react'; import { NameProvider } from './NameContext'; const ParentComponent = ({ name, children }: { name: string; children: React.ReactNode }) => { return Children.map(children, (child, childIndex) => { if (!isValidElement(child)) return child; const updatedInnerChildren = Children.map(child.props.children, (innerChild, innerIndex) => { if (!isValidElement(innerChild)) return innerChild; // 为每个MyComponent生成唯一name并提供Context const uniqueName = `${childIndex}-${innerIndex}-${name}`; return ( <NameProvider value={uniqueName}> {innerChild} </NameProvider> ); }); return cloneElement(child as ReactElement, { children: updatedInnerChildren, }); }); };
3. 在MyComponent中消费Context
import { useName } from './NameContext'; const MyComponent = () => { const name = useName(); console.log(name); // 现在可以正确获取到name值 return ( <div id={`${name}-component`}>...</div> ); };
内容的提问来源于stack exchange,提问作者Pollák Bence
相关产品推荐
相关产品推荐

