React clone元素来修改子组件,并将ref保存在功能组件中



我曾经在我的组件渲染时有refs,它工作:

// props.children is ReactElement<HTMLDivElement>[]
const [childRefs] = useState<RefObject<any>[]>(props.children.map(() => createRef()));
// working code, all the variables (props, childRefs etc) are defined earlier in scope
return <div {...props}>
{
props.children.map((c, i) => <div key={i} ref={childRefs[i]}>{c}</div >)
}
</div>

基本上,我使用refs命令直接设置一些转换到样式,因为鼠标移动在JSmousemove事件。

但是,我现在需要自动地将一些CSS类注入到传递的组件中。我已经创建了一个组件(名为Layer),它接受子元素,克隆它,设置CSS类,并返回它:
function Layer(props:LayerProps){
const elem = cloneElement(props.children, {...props.children.props,
className: styles['layer']
});
return elem;
}

我也像这样更新了主组件:

return <div {...props}>
{
props.children.map((c, i) => <Layer key={i} ref={childRefs[i]}>{c}</Layer>)
}
</div>

然而现在我的ref现在没有通过,可以理解,因为Layer功能组件不能有ref(因为它是一个功能)。当我尝试将ref设置为Layer时,它不能,并且有这个错误(可以理解):

(property) ref: React.RefObject<any>
Type '{ children: ReactElement<HTMLDivElement, string | JSXElementConstructor<any>>; key: number; ref: RefObject<any>; }' is not assignable to type 'IntrinsicAttributes & LayerProps'.
Property 'ref' does not exist on type 'IntrinsicAttributes & LayerProps'.ts(2322)

如果我尝试使用forwardRef转发ref,它没有任何东西可以设置ref,因为我只是修改传递的子元素并返回它,而不是返回像<div>...</div>这样的新元素,我可以转发像<div ref={forwardedRef}>...</div>这样的ref。

如何修改CSS类保持一个ref的对象?我知道如何做每一个(如果我只需要添加类IcloneElement,如果我只需要ref它,我使用forwardRef,并将其传递给JSX的子组件),但我无法弄清楚能够同时做到这两个。

我该怎么做?

好了,经过一番挖掘和实验,我意识到我可以给ref"prop"(这不是一个技术上真正的道具,但无论如何)在cloneElement就像任何道具。

我最终转发ref到功能组件,并提供ref作为新克隆元素的道具,它工作了。

然而,TypeScript定义错误地将ref属性标记为不存在,而它可以完美地工作。我需要它将道具转换为any以沉默linter错误:


const Layer = forwardRef((props:LayerProps, ref:any) => {
const elem = cloneElement(props.children, {
className: `${props.children.props.className ?? ''} ${styles['layer']}`,
ref: ref
} as any); // as any fixes ref complaining
return elem;
});

And in many component:

return <div {...props}>
{
props.children.map((c, i) => <Layer key={i} ref={childRefs[i]}>{c}</Layer>)
}
</div>

最新更新