skip to Main Content

How can I memoize a callback generated in the map loop? This (obviously) gives an error:

const SomeComponent = ({ items }: { items: ItemData[] }) => {
  const getItemCallback = (item: ItemData) => (e: React.MouseEvent) => {
    e.preventDefault();

    //do something with item
  }

  return <div>
    {items.map(item => {
      const callback = useCallback(getItemCallback(item));
    
      return <Item title={item.title} itemCallback={callback} />
    })}

  </div>
}

enter image description here

3

Answers


  1. const ItemList = ({ items }: { items: ItemData[] }) => {
      const getItemCallback = useCallback((item: ItemData) => (e: React.MouseEvent) => {
        e.preventDefault();
    
        //do something with item
      }, []);
    
      return (
        <div>
          {items.map(item => (
            <Item title={item.title} itemCallback={getItemCallback(item)} />
          ))}
        </div>
      );
    };
    
    const SomeComponent = ({ items }: { items: ItemData[] }) => {
      return <ItemList items={items} />;
    };
    Login or Signup to reply.
  2. Wrap getItemCallback in useCallback and pass it to the component:

    const SomeComponent = ({ items }: { items: ItemData[] }) => {
      const getItemCallback = useCallback((item: ItemData) => (e: React.MouseEvent) => {
        e.preventDefault();
    
        //do something with item
      }, []);
    
      return <div>
        {items.map(item => (
          <Item 
            key={item.key}
            item={item} 
            itemCallback={getItemCallback} 
            />
        ))}
      </div>
    }
    

    The component then calls the callback, and passes the item to create a new function wrapped with useCallback:

    const Item = ({ item, itemCallback }) => {
      const callback = useCallback(itemCallback(item), []);
      
      return (
        ...
      );
    }
    
    Login or Signup to reply.
  3. The a updated version of your code using

    const SomeComponent = ({ items }: { items: ItemData[] }) => {
          const getItemCallback = (item: ItemData) => (e: React.MouseEvent) => {
            e.preventDefault();
        
            //do something with item
          }
        
          return (
            <div>
              {items.map(item => {
                const callback = useMemo(() => getItemCallback(item), [item]);
                return <Item title={item.title} itemCallback={callback} />;
              })}
            </div>
          );
        };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search