问题复现
在 js 函数组件中,需要根据数组动态生成组件,用到 react-use 中的 useList,很容易想到用 Array.prototype.map 方法,而且在使用 JSX 语法生成组件的时候,要加 key,我这里使用了 nanoid 这个包来生成随机 key:
import React from 'react'
import { nanoid } from 'nanoid'
import useList from 'react-use/esm/useList'
import SubComponent from './SubComponent'
/* ... */
const Parent = () => {
const [dynamicSubComponents, {
clear, push
}] = useList(<></>)
const fetchData = async () => {
const arr = await fetch('/api/somedata').then(r = r.json())
if (Array.isArray(arr)) {
const temp = arr.map(item => <SubComponent key={nanoid(10)} />)
push(...temp)
}
}
useEffect(() => {
clear()
fetchData()
}, [])
return <>
{dynamicSubComponents}
</>
}
export default Parent
这样看起来没什么问题,但是控制台始终会报一个关于组件 Parent 中子元素的 key 错误。
解决方法
将 useList 的初始化值 [<></>] 改为 [<React.Fragment key={nanoid(10)}/>] 即可。
方法2:使用 TypeScript
之所以要传递初始化值,是因为在 JavaScript 环境中,hook 的泛型类型 ts 提示,是根据初始化值来断定的。如果直接使用 typescript 环境就没这个问题了。
const [dynamicSubComponents, {
clear, push
}] = useList<SubComponent>([])