简体   繁体   中英

React - useCallback throwing error on renderProps function

I'm passing renderProps function in the props. i want to wrap it with useCallback, so the optimised child component will no re-render on the function creation.

when wrapping the function with useCallback i get this error:

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app

none of the above applies to my situation.

renderCell = React.useCallback((
    {
      events,
      popperPlacement,
      popperStyle,
      time
    }
  ) => {
    const { localeToggle } = this.state;
    const { weekStarter, isTimeShown } = this.props;
    const eventsListPopperStyle = utils.isWeekFirst(time, weekStarter) ||
      utils.isWeekSecond(time, weekStarter) ? { left: '-17% !important' } : { left: '17% !important' };
    return (
      <MonthlyCell
        events={events}
        isTimeShown={isTimeShown}
        popperPlacement={popperPlacement}
        popperStyle={popperStyle}
        time={time}
        eventsListPopperStyle={eventsListPopperStyle}
      />
    )
  }, [])

Because hooks doesn't work inside class components, the error was thrown. I managed to find a work around by providing the second parameter for the React.memo. in the function i provided, i compare the prevProps and nextProps, and when the prop is a function i disregard it and return true. it might not work for everyone because sometime the function do change, but for situations when it's not, it's ok.

const equalizers = {
  object: (prevProp, nextProp) => JSON.stringify(prevProp) === JSON.stringify(nextProp),


  function: () => true, // disregarding function type props


  string: (prevProp, nextProp) => prevProp === nextProp,
  boolean: (prevProp, nextProp) => prevProp === nextProp,
  number: (prevProp, nextProp) => prevProp === nextProp,
}

export const areEqualProps = (prevProps, nextProps) => {
  for (const prop in prevProps) {
    const prevValue = prevProps[prop];
    const nextValue = nextProps[prop];
    if (!equalizers[typeof prevValue](prevValue, nextValue)) { return false; }
  }
  return true
}

export default React.memo(MyComponent, areEqualProps)

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