我正在写一个装饰一些孩子的小组件。鉴于以下示例:
const Child = props => <div>{props.name}</div>;
const Parent = props => {
let wrappedChildren = React.Children.map(props.children, c => {
return (<Decorator key={c.key}>
{c}
</Decorator>);
});
return (<div>
{wrappedChildren}
</div>);
}
const Consumer = props => {
let children = [0, 1, 2].map(num => {
return <Child key={num} name={num} />;
});
return <Parent>{children}</Parent>;
});
&#13;
在这段代码中,我想要带走每个孩子并用一些包装容器或某些行为来装饰它。忘记可能只有一个孩子的那一刻,我需要给每个实例一个密钥。
目前,我假设每个孩子都有一把不太棒的钥匙,把它从孩子身上移开并直接应用于装饰师。
这是&#34;正确&#34;这样做的方式?还有更好的方法吗?
答案 0 :(得分:2)
这适用于当前版本的React,15.6.1(也可能与之前的版本一样)。但是,有一个更好的方法可以通过一个小的调整来实现你的目标,这可以将提升委托给一个道具,而不是直接使用key
。
原因是密钥的概念是在组件创建之前由React内部控制的东西,因此它属于实现细节类别,结果是React的未来版本可能会破坏您的代码注意到它。
相反,您可以在Child
组件上使用道具,例如id
,基于您假设每个孩子确实具有某种独特价值。您的代码将导致:
const Child = props => <div>{props.name}</div>;
const Parent = props => {
return React.Children.map(props.children, c => {
return (<Decorator key={c.props.id}>
{c}
</Decorator>);
});
return (<div>
{wrappedChildren}
</div>);
}
const Consumer = props => {
let children = [0, 1, 2].map(num => {
return <Child id={num} name={num} />;
});
return <Parent>{children}</Parent>;
});
如果您有一个更复杂的结构并且想要避免单独传递道具,那么父组件应该负责为子项生成唯一ID。您可以按照此回答https://stackoverflow.com/a/29466744/4642844中解释的提示进行操作。
这些是我要遵循的步骤:
在componentWillMount
组件中实施Parent
以创建一系列唯一ID。您可以使用内部成员类变量而不是本地state
。它会是这样的:
componentWillMount() {
this.uuids = React.Children.map(() => uuid());
}
在Parent
渲染中,按以下方式将每个键分配给装饰器组件。
render() {
return React.Children.map(props.children, (c, i) => {
return (<Decorator key={this.uuids[i]}>
{c}
</Decorator>);
});
}
一些有用的链接:
http://mxstbr.blog/2017/02/react-children-deepdive/
https://medium.com/@dan_abramov/react-components-elements-and-instances-90800811f8ca
答案 1 :(得分:1)
我认为你的方法很好。而你确实需要顶层的钥匙。使用孩子的钥匙(如果有的话)。如果没有,请回到index
,正如React建议的那样:
当您没有渲染项目的稳定ID时,您可以将项目索引用作关键作为最后的手段。
请注意:
如果项目可以重新排序,我们建议不要使用密钥索引,因为这样会很慢。
const Child = props => <div>{props.name}</div>;
const Parent = props => {
let wrappedChildren = React.Children.map(props.children, (c, i) => {
const key = c.key ? `key-${c.key}` : `index-${i}`
return (
<Decorator key={key}>
{c}
</Decorator>
);
});
return (
<div>
{wrappedChildren}
</div>
);
};
const Consumer = () => {
let children = [ 0, 1, 2 ].map(num => {
return <Child key={num} name={num} />;
});
return <Parent>{children}</Parent>;
};
答案 2 :(得分:-1)
Javascript Array.map(fn)
实际上将3个参数传递给fn
秒作为索引。那么,你需要做的是:
let wrappedChildren = props.children.map((c, i) => <Decorator key={i}>{c}</Decorator>);