Context
I have a Redux state in which i have an array of items. Everytime you click a link in the menu, an item gets added to this array.
In one of my components, which is connected to the store using connect(mapStateToProps)(Component)
I map through this array and load the child components. These child components fetch data from an API.
Problem
Everytime a new item gets added to the array, all the child components re-render, because the array that it maps changes. I only want the newly added item to render and the rest persist as they are. I know you can do something with useMemo, but I'm not sure how to correctly use that with mapping.
Thanks to anyone who can help me!
You can use pure component for each item:
const id = ((id) => () => id++)(1);
const Item = React.memo(function Item({ item, increase }) {
const rendered = React.useRef(0);
rendered.current++;
return (
<li>
{item.id} - rendred {rendered.current} count:{' '}
{item.count}
<button onClick={() => increase(item.id)}>
increase count
</button>
</li>
);
});
const App = () => {
const [items, setItems] = React.useState([]);
const addItem = () =>
setItems((items) => [{ id: id(), count: 0 }, ...items]);
//use useCallback to create an increase function that
// never changes so you'll never pass a new increase
// function to item
const increase = React.useCallback(
//pass callback to state setter so items is not
// a dependency of the useCallback
(id) =>
setItems((currentItems) =>
currentItems.map((item) =>
item.id === id
? { ...item, count: item.count + 1 }
: item
)
),
[]
);
return (
<div>
<div>
<button onClick={addItem}>+</button>
</div>
<div>
{items.map((item) => (
<Item
key={item.id}
item={item}
increase={increase}
/>
))}
</div>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments