Why react does not re-render component when state is changed using setState

https://codesandbox.io/s/random-quote-machine-fl6tc.
Here is my code.
I have a click property inside state, it is change using handleGetQuote.

When ever the state is changed it should re render the componenet .

In my case it is not re rendering component. When ever a component is re rendered this.fetchQuote inside ComponetDidMount should be called.

On console logging, the state it is changing but re render is not happening
Why ??

First of all, please don’t post pictures of code. Links and/or cut and paste code.

So, when I put this into your code:

  fetchRandomQuote() {
    fetch("https://api.quotable.io/random")
      .then(response => response.json())
      .then(
        data => {
          console.log("here", data);
          this.setState({
            quote: data.content,
            author: data.author,
            isLoaded: true
          });
        },
        error => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      );
  }

I see that your fetch is always returning the same value as the first call. I’m guessing that there is some kind of caching on the api. But it doesn’t seem to be a problem with the sample apps.

Sorry I don’t have time to figure it out, but I hope that gives you somewhere to explore.

I think it is because React only partially renders depending on what changes. The quickest way to fix this would be to call this.fetchRandomQuote(); inside your handleGetQuote() function.

Although, this means you are running ‘fetch’ every time the user clicks the button which is not really ideal. On load (mount) you could store all the quotes in an array, then just access the array for a random quote rather than making a new request.

I hope this helps. I’m still learning myself. Happy Coding :slight_smile:

1 Like

I see that your fetch is always returning the same value as the first call. I’m guessing that there is some kind of caching on the api

What do you mean by this ??. If i reload the page it gives me a new quote

Yes!! Thank you.

Do you have any resource or link to read about following statement you made

I think it is because React only partially renders depending on what changes.

To be honest, no. I’m not even sure that it’s true :sweat_smile:, I just seem to remember reading about it (although I might be getting confused with conditional rendering / the shouldComponentUpdate hook). I know you can specify something not to render.

As I said, I’m still learning myself, so hopefully someone who knows React well can explain it for us :slight_smile:

1 Like

Ok the problem is that you call the wrong function when you click new quote. You call handleQuote function which does nothing. You need to call the function which does the request. You assign to onGetQuote the wrong function to be more precise.Also you need to make sure that this will point to the class when you assign it to the button. You can also use arrow functions and not think about what this will point to or use bind if you like that approach more. Also when you update your state that depends on your previous state as it is the case in handleGetQuote it s better to use function version of setState. Also when you get the response you should set loading to false since you got a response back, mostly you set it to true before you send the request then false when you got the response or error because you re done loading.

You did not understand my question

  1. My point is handleQuote function does change state using setState to when a state is changed it should re render the Component. But it is not doing the same !!!

  2. I have used stateless functional component that is why i have not used this.

  3. I m changing my isLoaded response to false or true in fetchQuote func

Thanks

I don t think React works that way. It does run your main function when it Mounts but that happens when you load that component. After that the component updates whenever the state changes, indeed but it will not Unmount and Mount again for each state change it would be very bad for performance, therefore all the changes will be handled via shouldComponentUpdate and componentDidUpdate. Your components do re render whenever you change the state but since fetching quotes function won t run again you don t see any change because there is nothing to see. If you would load other component in place of the existing one and then you would switch back then ye you would get other quote because the component Unmounted when you loaded another one in its place and then Mounted again.

Thanks for clearing my doubt. Do you have any link , blog or docs to read about the statement you made

It does run your main function when it Mounts but that happens when you load that component. After that the component updates whenever the state changes, indeed but it will not Unmount and Mount again for each state change it would be very bad for performance, therefore all the changes will be handled via shouldComponentUpdate and componentDidUpdate .

Here you have the lifecycle methods: https://reactjs.org/docs/react-component.html
There you also have a lifecycle diagram where you can check “Show less common lifecycles” option and also the React version.
You can also put some console.log in your Class component inside componentWillUnmount, componentDidUpdate and componentDidMount to see when each of them executes.
From that website:

Updating
An update can be caused by changes to props or state. These methods are called in the following order when a component is being re-rendered:

static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()