3

I am using a third party component that re-renders every time state changes which is good but in some instances I do not want it to re-render even if the state changes. Is there a way to do using react functional component. I have read online and it says use shouldComponentUpdate() but I am trying to use functional component and tried using React.Memo but it still re-renders

Code

const getCustomers = React.memo((props) => { useEffect(() => { }); return ( <> <ThirdPartyComponent> do other stuff {console.log("Render Again")} </ThirdPartyComponent> </> ) }); 
4
  • 4
    ...but in some instances I do not want it to re-render even if the state changes... this defeats the entire purpose of React. It seems like an XY problem, what are you actually trying to do? Commented Aug 18, 2020 at 14:27
  • Can you be more specific? Do you want to hold rendering in which situation? It's a pretty unusual usecase but still valid Commented Aug 18, 2020 at 14:44
  • @Dupocas Yes, I want to stop re-rendering in some instances because I am getting an error using another library that unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering. Commented Aug 18, 2020 at 14:48
  • Can you enrich your question or post a sandbox? Commented Aug 18, 2020 at 15:01

1 Answer 1

2

For props:

How do I implement shouldComponentUpdate?

You can wrap a function component with React.memo to shallowly compare its props:

const Button = React.memo((props) => { // your component }); 

It’s not a Hook because it doesn’t compose like Hooks do. React.memo is equivalent to PureComponent, but it only compares props. (You can also add a second argument to specify a custom comparison function that takes the old and new props. If it returns true, the update is skipped.)

For state:

There's no build in way to achieve this, but you can try to extract your logic to a custom hook. Here's my attempt to only rerender when shouldUpdate returns true. Use it with caution, because it's the opposite of what React was designed for:

const useShouldComponentUpdate = (value, shouldUpdate) => { const [, setState] = useState(value); const ref = useRef(value); const renderUpdate = (updateFunction) => { if (!updateFunction instanceof Function) { throw new Error( "useShouldComponentUpdate only accepts functional updates!" ); } const newValue = updateFunction(ref.current); if (shouldUpdate(newValue, ref.current)) { setState(newValue); } ref.current = newValue; console.info("real state value", newValue); }; return [ref.current, renderUpdate]; }; 

You would use it like this:

 const [count, setcount] = useShouldComponentUpdate( 0, (value, oldValue) => value % 4 === 0 && oldValue % 5 !== 0 ); 

In this case, a rerender would occur (due to usages of setcount) if, and only if, shouldUpdate returns true. i.e., when value is multiple of 4 and the previous value is not multiple of 5. Play with my CodeSandbox example to see if that's really what you want.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.