3

I have a pretty simple React.js component which I need to make an isomorphic (rendered on the server). The problem is that component rendered with helpful information only after ajax request completes, like that:

export default React.createClass({
  getInitialState() {
    return {}
  },

  componentDidMount() {
    fetch("/users/").then(response => {
      this.setState(users: response.data)
    })
  },

  render() {
    if (this.state.users == undefined) {
      return <div />
    }

    return <div>{this.state.users.map(some_function)}</div>
  }
})

The problem is that it's pointless to return empty div to search engines. I want ajax request to be finished (even on the server) and render only after that. How can I achieve that?

Aakash
  • 1,455
  • 13
  • 16
Alex Antonov
  • 14,134
  • 7
  • 65
  • 142
  • I believe that you want to take the parent component and use props instead of state, letting the parent component decide whether to render it or not. – rdiz Aug 01 '16 at 09:36
  • @Dencker Could you explain how to decide render it or not, please? – Alex Antonov Aug 01 '16 at 09:43

1 Answers1

6

As touched on by @Dencker, you want to make the parent component decide when to render the child component, something like this would work:

// Parent
export default React.createClass({
  getInitialState() {
    return {
      usersLoaded: false
    }
  },

  componentDidMount() {
    fetch("/users/").then(response => {
      this._users = response.users;
      this.setState({
        usersLoaded: true
      });
    })
  },

  render() {
    if ( this.state.usersLoaded ) {
      return (
        <ChildComponent users={this._users} />
      )
    } else {
      return null;
    }
  }
});

// Child
export default React.createClass({
  render() {
    return <div>{this.props.users.map(some_function)}</div>
  }
});

What I'm doing there is:

  1. Setting an initial state on the parent component which is usersLoaded: false.
  2. In the render function for that component, making sure I only render the child component when the parent's usersLoaded state is true.
  3. parent component's componentDidMount method is where the AJAX call takes place, and note I use a variable on the component to store the users, not the state object (states generally should only be used to store very simple values).
  4. This is then passed down to the child component as a prop.

All of the above makes the child component far simpler as it will only now need a render method and no if/else check.

maxcountryman
  • 1,562
  • 1
  • 24
  • 51
toomanyredirects
  • 1,972
  • 15
  • 23