Reputation: 2136
I'm new to Hooks and trying to create a PureComponent equivalent version with Hooks. My goal is to create a multiselectable list with a child component that is reponsible for rendering the list items:
const Movie: FunctionComponent<{
title: string,
score: number,
id: number,
isSelected: boolean,
setSelected: React.Dispatch<React.SetStateAction<{}>>
}> = React.memo(({ title, score, isSelected, setSelected, id }) => {
const selectMovie = (): void => {
if (isSelected === null)
return;
setSelected(id);
};
const selected = {
backgroundColor: "blue"
}
console.log("render movie")
return (
<div onClick={selectMovie} style={isSelected ? selected : {}}>
{title}, {score}
</div>
)
})
The parent component have the data as well as the logic for the selection:
const App: FunctionComponent = () => {
const data = [
{
id: 1,
title: "Pulp fiction",
score: 9
},
{
id: 2,
title: "Heat",
score: 8
},
{
id: 3,
title: "American pie",
score: 7
}
]
const [selectedItems, setSelected] = React.useState<{}>({});
const selectMovie = React.useCallback((id: any) => {
const sel: any = {...selectedItems};
if (sel.hasOwnProperty(id)) {
delete sel[id]
} else {
sel[id] = true;
}
setSelected(sel);
}, [selectedItems])
return (
<div>
{
data.map(e => <Movie key={e.id} {...e} setSelected={selectMovie} isSelected={selectedItems.hasOwnProperty(e.id)}/>)
}
</div>
)
}
I made a sandbox where you can try it out: https://codesandbox.io/s/old-sun-38n4u
The selection state is maintained in the parent component in an object and supplied to the child as a boolean. The problem is when I click on a movie all 3 list items re-renders (you can see the log in the console). I have used React.memo
and useCallback
as well to avoid arrow function re-creation for the props comparison. I'm pretty new to hooks, so it must be something silly I'm overlooking...
Upvotes: 2
Views: 832
Reputation: 416
That is because your selectMovie is changing every time due to selectedItems dependency changing.
setSelected function can also take a function and you can get the selectedItems value so you don't need to set it as a dependency
Upvotes: 2