Need help with get requests in Axios

I am working on an app using react native where i make a get request to recieve a single row. I want to assing this data to state and use the data as text. However, it logs properly but when i pick out a key and use in the component i get an error :

“Cannot read property ‘bookname’ of null”

Here is the code of the component

 import React, {Component} from 'react';
import {Text, View, StyleSheet} from 'react-native';
import Axios from 'axios';

export default class Bookscreen extends Component {
  constructor(props) {
    super(props);
    this.state = {
      book_id: null,
      data: null,
      isLoading: true,
    };
  }
  componentDidMount() {
    let id = this.props.route.params.ID;
    console.log(id);
    return Axios.get('NOTSHOWINGMYIP/book', {params: {id: id}})
      .then((response) => {
        this.setState({
          data: response.data,
          isLoading: false,
        });
        console.log(this.state.data);
      })
      .catch((error) => {
        console.log(error);
      });
  }
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.heading}>{this.state.data.bookname}</Text>
        <View style={styles.democolor}></View>
        <View style={styles.ratings}>
          <Text>Lorem</Text>
          <Text>Ipsum</Text>
        </View>
        <View>
          <Text style={styles.description}></Text>
        </View>
        <View style={styles.discussion}>
          <Text>Lorem ipsum</Text>
        </View>
        <View style={styles.similarSuggestions}></View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  democolor: {
    backgroundColor: 'blue',
    flex: 3,
  },
  heading: {},
  linkButton: {},
  discussionButton: {},
});

When you render, the fetch hasn’t completed. So you are trying to access something that is null, hence the error. Normally you do something like (note there are shorter ways to write this, I’m just writing it out for clarity):

render() {
  if (thingIWant == null) {
    return null;
 } else {
    return /* JSX here */;
  }
}

Basically return null (or maybe some empty state/loading component) when there is no data, and the stuff you actually want to display when there is data. Once the data arrives and the state is set, the component rerenders, this time with data.

but doesnt componentDidMount complete the fetch before rendering the component
?

Nope, it occurs after mount – the component has been mounted, the DOM nodes are ready etc. It has already rendered. It will render again if you set the state.

You do not want it to block until the fetch completes, even if you think you do. You need the ability to introduce things like loading states, if it blocks rendering until the fetch completes you lose the ability to do that

You’re right. I did not have the Activity Indicator conditional. But it isn’t solving the issue. this.state.data.bookname is still blank. In fact. console.log(this.state.data) gives me a proper output.


Still the individual properties are undefined.

That is because this.state.data returns an array. You want the first element in that array:
this.state.data[0]
Then you can get the properties of the object.

Hope this helps

Thanks,that worked. But isnt it supposed to assign an object literal to this.state.data? Because i tried inserting the whole data inside the text component and it indicated that it is an object.

That entirely depends on how the data is sent/how the dev set it up.

I always hope my data is returned in an array, but sometimes it gets returned as anything from an object literal (bad practice), to an HTML node (security threat).

It should be common practice for JSON to be sent.

Data is set to be transferred as JSON. But doesn’t axios convert the data into an object literal on reception? I made the same get request in another component but for all rows in the table and rendered it in a flatlist. I didn’t need to access the data by accessing the first array item.

Yes, Axios will run the JSON.parse step for you & give you whatever the resource is under data, so if it’s an object, you get an object, if an array an array etc.

In this case, the log seems to be showing that you’re getting an array with a single item in it as the response from the API.

1 Like

You need to remember, the flat list iterates through each element of an array. So, there is no need to select the first element.

For the above question, you needed to hard-code indexing into the array. This is fine, as long as you are sure you always want just 1 element (the first that is returned).

1 Like