'React.useMemo is re-rendering all items in array

I have a react component that stores a set of fruits in useState. I have a memoized function (visibleFruits) that filters fruits. I map visibleFruits to the dom.

The problem is, when i check a fruit, all visible fruits re-render.

I am expecting that only the selected one re-renders since it is the only one that is changing.

Is there a way for me to use this pattern but prevent all from re-rendering on check?

In real life, there is a complex function in visibleFruits useMemo. So I can't simply append the filter before the map.

Edit, here is updated edit:


const Example = () => {
    const [fruits, setFruits] = React.useState([
        { id: 1, name: 'apple', visible: true, selected: false },
        { id: 2, name: 'banana', visible: false, selected: false },
        { id: 3, name: 'orange', visible: true, selected: false }
    ])

    const visibleFruits = React.useMemo(() => {
        return fruits.filter((f) => f.visible)
    }, [fruits])

    const handleCheck = (bool, id) => {
        setFruits((prev) => {
            return prev.map((f) => {
                if (f.id === id) {
                    f.selected = bool
                }
                return f
            })
        })
    }

    return (
        <div>
            {visibleFruits.map((fruit) => {
                return <FruitOption fruit={fruit} handleCheck={handleCheck} />
            })}
        </div>
    )
}

const FruitOption = ({ fruit, handleCheck }) => {
    console.log('** THIS RENDERS TWICE EVERY TIME USER SELECTS A FRUIT **')
    return (
        <div key={fruit.id}>
            <input
                checked={fruit.selected}
                onChange={(e) => handleCheck(e.target.checked, fruit.id)}
                type='checkbox'
            />
            <label>{fruit.name}</label>
        </div>
    )
}

export default Example


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source