Search code examples
reactjsreact-memo

Error in Component re draw with memoized React component


This is my navbar component. Exports a memoized one.

import * as PropTypes from 'prop-types';
import Style from './Navbar.module.scss';
import NavbarItem from './NavbarItem';
import React from 'react';

/**
 * @param items
 * @param type
 */
export default function Navbar({ items }) {
  return (
    <nav className={Style.main}>
      {items.map((item, i) => (
        <NavbarItem name={item.name} url={item.url} items={item.items} key={item.name + i} />
      ))}
    </nav>
  );
}

export const MemoizedNavbar = React.memo(Navbar, true);

Navbar.propTypes = {
  items: PropTypes.array.isRequired,
  type: PropTypes.string,
};

Header that uses the Navbar.

import React, { Fragment, useContext } from 'react';
import Logo from './Logo';
import { MemoizedNavbar } from '../Navbar/Navbar';
import Style from './Header.module.scss';
import { ListContext } from '../../lib/Context/ListContext';
import BrandsHelper from '../../lib/List/BrandsHelper';
import { Items } from '../../config/SiteNavbar';
import Svg from '../Utils/svg';

const {useState} = require("react");

export default function Header({ brand }) {
  const [lists, setLists] = useContext(ListContext);

  const listData = lists.lists[lists.currentListId];

  const [hamburgerMenuOpen, setHamburgerMenuOpen] = useState(false);


  const handleHamburgerClick = () => {
    setHamburgerMenuOpen(!hamburgerMenuOpen);
  }

  return (
    <header className={Style.header}>        
      <section className={Style.section}>
        <Logo brand={brandName} />
        <MemoizedNavbar items={Items} />

        <button className={Style.hamburgerButton} aria-label="Menu" onClick={handleHamburgerClick}>
          <span className={Style.hamburgerButtonClickable} />
        </button>

      </section>
    </header>
  );
}

When I click in the HambugerButton, I get the following error:

enter image description here

If I don't use the Memoized component, it works just well.

What could be wrong?


Solution

  • export const MemoizedNavbar = React.memo(Navbar, true);
    

    The second argument is expected to be a function, like:

    function areEqual(prevProps, nextProps) {
      /*
      return true if passing nextProps to render would return
      the same result as passing prevProps to render,
      otherwise return false
      */
    }
    

    If you don't need to do anything particular, just drop the second argument, and react will do a shallow comparison.

    export const MemoizedNavbar = React.memo(Navbar);