user6761897
user6761897

Reputation:

State nulls out inside render function in React

I have a component where I make an API call to get data pertinent to an user. Here's my code,

class Header extends React.Component {

  constructor(props) {
    super(props);
    this.state = { user: null };

  }

  componentDidMount() {

    getUserData(xobni_api).then((data) =>{
      this.setState({user : data});
      console.log(this.state.user);//A


    });
  }
  render() {
    return (
      <div className="header">
        <Masthead user={this.state.user.fullName} />//B
        <PrimaryNav/>

      </div>
    );
  }
}
export default Header;

At line A, I can render the details of the user, while at line B user is null and I'm getting an error. What am I missing. I've tried making the API calls inside both componentDidMount() and componentWillMount(). Any help appreciated.

Upvotes: 1

Views: 57

Answers (2)

xiaofan2406
xiaofan2406

Reputation: 3310

On the initial render, this.state.user is null, and you were trying to get fullname property from a null object, so you get an error.

To fix, change line B to:

{this.state.user && <Masthead user={this.state.user.fullName} />}

Upvotes: 0

azium
azium

Reputation: 20614

The first time your component renders this.state.user is null, right? That's what you set it as in your constructor. Therefore this.state.user.fullName is equivalent to null.fullName which will crash.

You either need to make your initial state representative of the shape of your user object, or you need to do a null check before rendering the component:

render() {
  return (
    <div className="header">
      {this.state.user && // <-- check if truthy
        <Masthead user={this.state.user.fullName} />
      }
      <PrimaryNav />
    </div>
  )
}

Because you're doing an ajax request, you can also use this opportunity to display a loading indicator:

render() {
  return (
    <div className="header">
      {!this.state.user && // <-- if user is still null
        <div>Loading...</div>
      }

      {this.state.user && // <-- check if truthy
        <Masthead user={this.state.user.fullName} />
      }
      <PrimaryNav />
    </div>
  )
}

Upvotes: 3

Related Questions