从controlled 与uncontrolled 组件的角度考虑可能会有所帮助。您可能从<input>s 等核心元素中对此很熟悉,您可以传入defaultValue 属性,让输入处理所有内容(“不受控制”),或者您可以传入value 和@987654326 @ 并自己处理事情(“受控”)。您也可以将表格组件设计为受控组件或非受控组件。
作为一个不受控制的组件,你可能会传入一个设置初始排序的道具,但之后一切都由表格处理。父级不会收到通知,也不会更新其状态:
const Parent = () => {
const [items, setItems] = useState(/* some array */);
return <MyTable items={items} defaultSort="asc" />
}
const MyTable = ({ items, defaultSort }) => {
const [sort, setSort] = useState(defaultSort ?? 'asc');
const sortedItems = useMemo(() => {
if (sort === 'asc') {
return [...items].sort(/* insert sort function here */)
} else {
return [...items].sort(/* insert sort function here */)
}
}, [items, sort]);
return (
<>
<button onClick={() => setSort(sort === 'asc' ? 'dsc' : 'asc')}>
Change Sort
</button>
{sortedItems.map(() => /* etc */)}
</>
)
}
如果你做一个受控组件,那么父母负责状态,孩子只是通知父母相关的变化
const Parent = () => {
const [items, setItems] = useState(/* some array */);
const [sort, setSort] = useState('asc');
const sortedItems = useMemo(() => {
if (sort === 'asc') {
return [...items].sort(/* insert sort function here */)
} else {
return [...items].sort(/* insert sort function here */)
}
}, [items, sort]);
return <MyTable items={sortedItems} onSortToggled={() => setSort(sort === 'asc' ? 'dsc' : 'asc')} />
}
const MyTable = ({ items, onSortToggled}) => {
return (
<>
<button onClick={onSortToggled}>
Change Sort
</button>
{items.map(() => /* etc */)}
</>
)
}
如果您添加一些额外的代码来检查未定义项,则可以使您的表同时支持受控和不受控模式,具体取决于传递的道具集。但它应该只是其中之一;您不应该尝试让两个组件同时管理状态,因为这只会增加状态不同步和引入错误的机会。
必须更改存储项目的状态,这在我的表格组件之外
如果这是您的要求之一,那么您基本上是在做受控组件版本,因此您必须接受父组件中描述如何执行此操作的函数。父组件是唯一知道自己拥有什么状态以及如何更新它的组件。