説明
- I have searched the issues of this repository and believe that this is not a duplicate.
What problem does this feature solve?
In complex applications where normalized data is managed in a global state like redux, a list component may receive an array of ids in a form of number[] or string[].
One way is to map these ids into data objects with useSelector like (between some complicated relations):
const dataSource = useSelector(s => props.ids.map(i => {
const post = s.entities.posts[i];
const author = s.entities.users[post.author];
return {
...post,
author,
};
}));
This solution works as expected but has a terrible performance because it creates new post object on every run, rows and columns re-renders then.
Another way is to pass id array to Table and select data inside column's render component like:
const AuthorEmail = ({id}) => {
const email = useSelector(s => s.entities.users[id].email);
return <span>{email}</span>;
};
const columns = [
{
title: 'Author Email',
key: 'authorEmail',
render(id) {
return <AuthorEmail id={id} />
},
},
];
<Table columns={columns} dataSource={ids} />
By introducing AuthorEmail component to directly select a very fine-grained part of state, we can eliminate most unexpected re-renders, also this pattern works perfectly with future state management framework recoil where entity data can be managed separately in large amount of atoms, which can't be mapped from an array of id.
Currently Table can be used in the way - except typescript warns:
Type 'number' does not satisfy the constraint 'object'. ts(2344)
Table#dataSource is declared as object[] so that number[] can't be its value: https://codesandbox.io/s/withered-platform-t3wg0?file=/src/App.tsx
What does the proposed API look like?
Have a loose dataSource type constraint so that it accepts primitive dataSource