React-Native and Fetch API rendering problems (Solved(?) and Q/A)

React-Native and Fetch API rendering problems (Solved(?) and Q/A)
0

#1

EDIT

It has come to my attention that running the app in debug mode caused this problem in the first place. Running it in normal will allow the fetch api to run as intended.

Sigh.

END EDIT

I haven’t been on FCC for a long while, mostly because I’ve been working on my own React-native app!

I came across this little problem when learning how to use the FETCH Api.
So I’ve been building an app that uses the Fetch API to make a request. Unfortunately, I think the code shown in the Facebook docs are (may be?) incorrect.

Problem

When starting the app, Fetch makes a call to a URL to pull JSON data.

componentDidMount(){
 return fetch(REQUEST_URL)
 .then((response) => response.json())
 .then((responseJson) => {
    this.setState({
      isLoading: false,
      data: JSON.stringify(responseJson)
    })
  })
  .catch((error) => {
    console.error(error);
  });
}

This is similar to the code that Facebook docs give as an example.

The problem is that when I start the app, the data doesn’t render in the render function.

render() { if (this.state.isLoading) { return ( <View style={{flex: 1, paddingTop: 20}}> <ActivityIndicator /> </View> ); } var data = this.state.data; return this.renderData(data); }

At least, it doesn’t render until after I click/touch the screen. Once I touch the screen, the data renders. Otherwise, it just stays in a perpetual “loading” state.

Solution?

I remembered that sometime in the past, I had to bind event handlers to their respective controls (this.handleClick = this.handleClick.bind(this), for example)

And that got me thinking: Where is this in the promise request? Where does this point to?

componentDidMount(){ return fetch(REQUEST_URL) .then((response) => response.json()) .then((responseJson) => { this.setState({ <--- **Where are you going?** isLoading: false, data: JSON.stringify(responseJson) }) })

I console.logged “this” within the responseJson promise, and it does point to the component, but I’m not convinced. With it being buried inside of the promise, I don’t think the this.setState function is actually able to set the component’s State.

So I made a variable before the fetch request.

const that = this; return fetch(REQUEST_URL) .then((response) => response.json()) .then((responseJson) => { that.setState({ isLoading: false, data: JSON.stringify(responseJson) }) })

Now I’m not a software guru. I’ve been teaching myself this stuff for the last couple of years, so my logic is off half the time.

So if my reasoning is correct or incorrect, please let me know! What I do know is that this is working for me; once the data is fetched, it automatically sets the state and reloads, showing me the JSON data when rendered.

Any thoughts? Am I completely off here? Am I missing anything?

Check this out on the original stack overflow post that I recently posted

Stack Overflow link


#2

It seems strange that you have to do response.json() and then JSON.stringify on that.
Is that necessary?
I’ve not used fetch much - I’ve used Axios but I have done a similar thing to pass the context into another function:

renderDisplay() {
    var thisContext = this;
    return (<div className="container">
        <header>
        <h1 className="text-center">Online Recipe Book</h1> 
          <button onClick={this.addNewClick}>ADD RECIPE</button>
        </header>
        <div  className="recipe-container">
         {this.state.recipes.map(function(r,i) {
          return (<Recipe 
                    onChange={thisContext.updateRecipe}
                    id={r.id}
                    key={i} 
                    name={r.name}
                    ingredients={r.ingredients} 
                    instructions={r.instructions}
         />)
          })}
       
        </div>
      </div>)
  }

#3

Without the Stringify, React native throws an Object error. I’m still doing some work with this, but I’ll update this thread as I find out more info.