3

I have a pure functional component where I fetch some data using useEffect. I pass in an empty string to useEffect, so it acts like a component did mount.

const getData = () => {
    setTimeout(() => {
        setLocalState({ a: 2 });
        setIsLoading(false);
    }, 0);
};

useEffect(() => getData(), []);

My entire component re-renders twice right now. I want to control this behavior and only re-render with certain conditions.

Here, I want the component to reRender when setLocalState has set the localState but not when setIsLoading has set isLoading to false.

Here's a code sandbox for this problem: https://codesandbox.io/s/0oyp6j506p

skyboyer
  • 22,209
  • 7
  • 57
  • 64
  • Can you just set isLoading to false with `isLoading = false` instead of `setIsLoading(false)`? The `useState()` hook works just like `this.setState({ ... })` in a `class` component, and by definition, changing `state` in that way causes a re-render. – sallf Mar 06 '19 at 04:13
  • @sal I actually thought about it, but it doesn't help my case because if I place – Arshpreet Singh Bhatti Mar 06 '19 at 18:51
  • @sallf I was trying to edit the ^ above comment but I timed out. I agree that it is a solution to declare the `isLoading` a variable in a normal way instead of tying it up with `useState` and getting a setter method from `useState`. But I want to find out a way to stop a re-render on the lines of `shouldComponentUpdate` where I `setState` for a variable using `useState` but stop it from re-rendering because it isn't necessary. – Arshpreet Singh Bhatti Mar 06 '19 at 18:57
  • **Update** - It doesn't help to declare `isLoading` as a `variable` or with the keyword `let` because I set it to false right after I `setLocalState({data})`. But that doesn't cause a re-render and hence `isLoading` just remains true. – Arshpreet Singh Bhatti Mar 06 '19 at 19:31
  • So `if (condition) { setIsLoading(bool) } else { isLoading = bool }`. That should work for what you're asking, though can't say it's best practice. If that doesn't work, can you be more specific with what you're trying to accomplish? – sallf Mar 06 '19 at 22:48

1 Answers1

1

If we call multiple state setters outside of react based events will trigger multiple renders but in class components state changes will be batched together. But in long term plan this will be fixed which is mentioned here

This appears to be normal React behavior. It works the exact same way if you were to call setState() in a class component multiple times.

React currently will batch state updates if they're triggered from within a React-based event, like a button click or input change. It will not batch updates if they're triggered outside of a React event handler, like a setTimeout().

I think there's plans long-term to always batch events, but not sure on the details.

mabhijith95a10
  • 436
  • 1
  • 4
  • 7