I'm doing a library project (see the link for more explaination) with react
, redux-toolkit
and typescript
.
I'm doing an addToWishlist
funcionality: the user simply click on the star, the code dispatches the action which patch the database and the state is updated. There is another action to remove the book from the list.
In <Wishlist />
component I want of course render the titles and other data of each book. So I useAppSelector
to retrieve wishlist
and the entire list
of books, and with help of filter
and map
I would get the corresponding books, but I'm not able to render them, because it gives me a ts
error: index.d.ts(1373, 9): The expected type comes from property 'children' which is declared here on type 'DetailedHTMLProps<HTMLAttributes<HTMLUListElement>, HTMLUListElement>'
Important note about the structure
wishlist
is an array of strings, which are the ids of the books.
The entire list
of books instead, is an array of objects: every object is a book, with title, author, id etc.
My questions:
What is going wrong here?
Basically, is it better to save in the
wishlist
array the ids (like I've done) and so I've to retrieve the data of books in my<Wishlist />
component withfilter
andmap
, or is it better to save the entire book (or at least, the infos that I need), so that is more easy to have the data?Which is the best practice, to render the list, in the first case, where I have to retrieve data using
filter
andmap
?
Here is the attempt:
const Wishlist = () => {
const dispatch = useAppDispatch();
const wishlist = useAppSelector(state => state.user.userInfo.wishlist);
const list = useAppSelector(state => state.catalogue.list);
const renderBooks = () => {
return wishlist.map(wishId => {
list.filter(book => {
if (book.id === wishId) {
return (
<li>{book.title}</li>
)
}
})
})
}
return (
<ul>
{renderBooks()}
</ul>
)
};
export default Wishlist;
Edited - maybe the problem is not the concatenation of methods, but something in the function calling?
Another more little example, with another solution, but same problem
interface fakeObj {
id: string;
name: string;
}
const fakeIds = ['5', '12', '878'] // this is my 'wishlist', containing only ids
const fakeList: fakeObj[] = [ // this is my 'list', containing objects, which were single books
{ id: '334', name: 'Tony' },
{ id: '5', name: 'Milly' },
{ id: '12', name: 'Jack' },
{ id: '7', name: 'Stew' },
{ id: '878', name: 'Mark' },
{ id: '87998', name: 'Greg' }
]
const renderArray = () => {
const arr: fakeObj[] = [];
fakeIds.forEach(id => {
fakeList.filter(obj => {
if (obj.id === id) {
arr.push(obj)
}
})
})
return arr; // the returned array is what I want: an array continaing the objects that i need
}
return (
<ul>
{/* The problem actually is here! */}
{renderArray()}
</ul>
)