如您所知,您不能只这样做:
// DON'T DO THIS
{rows.map((row, index) => (
<tr key={index}>{row}</tr>
))}
正如文档所说,这是“最后的手段”,实际上只对静态列表有用。你说过你的列表不会是静态的。
拥有像这样的已经创建的元素数组而不是元素的数据数组是相当不寻常的。如果你能避免它,我会,并给数据条目持久的 ID 值,你可以用作键,例如(name
显然是实际数据的替代品):
class RowInfo {
static id = 0;
constructor(name) {
this.name = name;
this.id = RowInfo.id++;
}
}
function RowList() {
const rows = [new RowInfo("one"), new RowInfo("two"), new RowInfo("three"), new RowInfo("four")];
return (
<>
{rows.map(({id, name}) => (
<tr key={id}><Row name={name}/></tr>
))}
</>
);
}
这假设它们都应该是相同类型的组件,当然,这可能不是真的。
如果您不能这样做并且必须预先创建实际元素,我可能会创建包装器对象:
class RowInfo {
static id = 0;
constructor(element) {
this.element = element;
this.id = RowInfo.id++;
}
}
function RowList() {
const rows = [new RowInfo(<Row0 />), new RowInfo(<Row1 />), new RowInfo(<Row2 />), new RowInfo(<Row3 />)];
return (
<>
{rows.map(({id, element}) => (
<tr key={id}>{element}</tr>
))}
</>
);
}
或者,如果它们没有您需要指定的任何props,您可以让 React 跟踪它们,因为这是其工作的一部分:
class RowInfo {
static id = 0;
constructor(Comp) {
this.Comp = Comp;
this.id = RowInfo.id++;
}
}
function RowList() {
const rows = [new RowInfo(Row0), new RowInfo(Row1), new RowInfo(Row2), new RowInfo(Row3)];
return (
<>
{rows.map(({id, Comp}) => (
<tr key={id}><Comp/></tr>
))}
</>
);
}
这是一个活生生的例子:
const Row0 = () => <div>Row 0</div>;
const Row1 = () => <div>Row 1</div>;
const Row2 = () => <div>Row 2</div>;
const Row3 = () => <div>Row 3</div>;
const {Fragment} = React;
class RowInfo {
static id = 0;
constructor(Comp) {
this.Comp = Comp;
this.id = RowInfo.id++;
}
}
// Have to use <Fragment></Fragment> in the below instead of <></> because
// Stack Snippet's version of Babel is out of date and
// doesn't understand <></>.
function RowList() {
const rows = [new RowInfo(Row0), new RowInfo(Row1), new RowInfo(Row2), new RowInfo(Row3)];
return (
<Fragment>
{rows.map(({id, Comp}) => (
<tr key={id}><Comp/></tr>
))}
</Fragment>
);
}
ReactDOM.render(<RowList/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>