import React, { useState, useEffect, useCallback } from "react";
export const Root = () => {
const [items, setItems] = useState(["A", "B"]);
const _onClick = useCallback( item => {
return () =>alert(item);
},[]);
return (
<>
<button onClick={() => setItems(["A", "B", "C"])}>Button</button>
{items.map((item, index) => (
<Item key={index} item={item} onClick={_onClick(item)} />
))}
</>
);
};
const Item = React.memo(({ item, onClick }) => {
useEffect(() => {
console.log("Item: ", item);
});
return <button onClick={onClick}>{item}</button>;
});
How do we stop the re-rendering of A and B? The result I want is to be a memo on the console when the button is pressed and "Item: C".
Because onClick
of <Item/>
is new every time it is rendered, it will cause A and B to re-render.
You can use React.memo
second parameter to check, for example:
const Item = React.memo(({ item, onClick }) => {
// ...
return <button onClick={onClick}>{item}</button>;
}, (prevProps, nextProps) => {
console.log(Object.is(prevProps.onClick, nextProps.onClick)); // console: false
});
More see doc.
In your code, _onClick(item)
will return new callback every render.
<Item key={index} item={item} onClick={_onClick(item)} />
You can change _onClick
to this:
const _onClick = useCallback(item => alert(item), []);
Next, pass _onClick to Item, and change how button's onClick is executed.
<Item key={index} item={item} onClick={_onClick} />
//...
<button onClick={() => onClick(item)}>{item}</button>
The full code is as follows:
import React, { useCallback, useState } from 'react';
export const Root = () => {
const [items, setItems] = useState(['A', 'B']);
const _onClick = useCallback(item => alert(item), []);
return (
<>
<button onClick={() => setItems(['A', 'B', 'C'])}>Button</button>
{items.map((item, index) => (
<Item key={index} item={item} onClick={_onClick} />
))}
</>
);
};
const Item = React.memo(({ item, onClick }) => {
useEffect(() => {
console.log("Item: ", item);
});
return <button onClick={() => onClick(item)}>{item}</button>;
});