SonOfNye
SonOfNye

Reputation: 75

How does render() actually execute?

I'm working on a project and I have created an interesting challenge for myself.

render() {
    const sysObjs = this.state.systemObjects;
    const jsonPackage = sysObjs[0];

    if(typeof jsonPackage === 'undefined'){
    console.log("undefined!!!")
    } else {
      //let jsonData = JSON.parse(jsonPackage.replaceAll("\\\\", "\\"));
      console.log(jsonPackage.replaceAll("\\\\", "\\"));
    }
   
    console.log(jsonPackage.replaceAll("\\\\", "\\"));

If I run that it will fail and it will fail on the last line of the snippet and it will fail because from the perspective of that line of code jsonPackage is undefined and we get a "cannot read property 'replaceAll' of undefined. That makes sense to me as doing any sort of operation on something that is undefined would fairly difficult. The part that is confusing me though is that if I remove that last line then the code will execute. That's confusing to me because that console.log is also there within the if-else block so I would imagine that both should throw errors but they don't. In fact if I run that after removing the last line I will actually get both sections of the if-else block to log to the console and that tells me that this is executing in a way that I don't understand. Can anyone explain what's happening for me? At the root here something is doing something such that the const jsonPackage is not populated immediately when it is set so I'm curious how react actually handles something like that.

Lastly, I commented out that line because that line throws "Unhandled Rejection(Error) A cross-origin error was thrown." I'm also not too sure what that actually means either as it wasn't covered in the course I took.

Upvotes: 0

Views: 46

Answers (2)

Chris Sandvik
Chris Sandvik

Reputation: 1927

I think you answered your own question. This is happening because the first time your code is executing, jsonPackage is not defined. This is why both blocks of your if statement are logging, because during the first pass though it is undefined and during the second it is, which will cause the else block to fire.

And this is why your code is breaking, during the first pass through of render, jsonPackage is not defined which will throw an error.

Its not really possible to explain why it's not defined the first time around without seeing the rest of your code. As a rule of thumb however, you should generally never assume that a React state value will always be defined and add checks accordingly.

Upvotes: 0

jnpdx
jnpdx

Reputation: 52655

render() is called each time your component's state updates. It can also get called in a number of other circumstances, but I think that's the relevant one for this situation.

You're not showing all of your code, but there is probably something running on mount or something similar that updates this.state.systemObjects.

On the first render of the component, this.state.systemObjects is undefined. So, if you have your console.log(jsonPackage.replaceAll("\\\\", "\\")); line in at the end of your render, it will fail because it can't do an operation on undefined. However, with it commented out, it runs fine, because it goes through the if(typeof jsonPackage === 'undefined'){ section of your if clause and not the else clause, where an operation is done on jsonPackage.

Then, once systemObjects is updated, render runs again. On that pass, systemObjects now is not undefined, so the else clause gets run -- since you don't have an undefined value any more, that else clause runs fine.

Your cross-origin error is not caused by any code you've shown -- it's probably caused by an API request somewhere. There are plenty of answers on SO about what can cause those.

Upvotes: 1

Related Questions