简体   繁体   中英

React w/hooks: prevent re-rendering component with a function as prop

Let's say I have:

const AddItemButton = React.memo(({ onClick }) => {
  // Goal is to make sure this gets printed only once
  console.error('Button Rendered!');
  return <button onClick={onClick}>Add Item</button>;
});

const App = () => {
  const [items, setItems] = useState([]);

  const addItem = () => {
    setItems(items.concat(Math.random()));
  }

  return (
    <div>
      <AddItemButton onClick={addItem} />
      <ul>
        {items.map(item => <li key={item}>{item}</li>)}
      </ul>
    </div>
  );
};

Any time I add an item, the <AddItemButton /> gets re-rendered because addItem is a new instance. I tried memoizing addItem:

 const addItemMemoized = React.memo(() => addItem, [setItems])

But this is reusing the setItems from the first render, while

 const addItemMemoized = React.memo(() => addItem, [items])

Doesn't memoize since items reference changes.

I can'd do

 const addItem = () => {
   items.push(Math.random());
   setItems(items);
 }

Since that doesn't change the reference of items and nothing gets updated.

One weird way to do it is:

  const [, frobState] = useState();
  const addItemMemoized = useMemo(() => () => {
    items.push(Math.random());
    frobState(Symbol())
  }, [items]);

But I'm wondering if there's a better way that doesn't require extra state references.

The current preferred route isuseCallback , which is the same as your useMemo solution, but with additional possible optimizations in the future. Pass an empty array [] to make sure the function will always have the same reference for the lifetime of the component.

Here, you also want to use the functional state update form , to make sure the item is always being added based on the current state.

  const addItem = useCallback(() => {
    setItems(items => [...items, Math.random()]);
  }, []);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM