0

I have a view that contains several components.

class ProfileView extends React.Compnent {
  constructor() {
    super();
    this.state = {
      user: {}
    }
  }
  componentWillMount() {
    fetchData((res) => {
      this.setState({user: res});
    })
  }
  render() {
    return (
      <div>
        <SomeComponent user={this.state.user} />
        <AnotherComponent />
      </div>
    )
  }
}

Since this is making an async call and rendering the state as an empty object on the initial redner, it's causing what I think to be a problem?

Inside my inner component I have to write validation, which is ok but feels wrong, that is why I am asking this question, is the validation in the example below good practice or am I making a mistake.

class SomeComponent extends React.Compnent {
  render() {
    if(typeof this.props.user !== 'undefined' && !$.isEmptyObject(this.props.user)) {
      return (
        <div>
          <SomeComponent user={this.state.user} />
          <AnotherComponent />
        </div>
      )
    } else {
      return (
        <div></div>
      )
    }
  }
}

This is the best I could come up with, it works ok but there is a slight jump in my UI because initially I am just rendering a <div>.

How can I improve my approach, or is this the ideal way to do it?

3
  • Just change your parent component to not render SomeComponent when data is not ready. Commented Jun 9, 2016 at 0:47
  • Passing props to child component is the right way. The code looks good. Commented Jun 9, 2016 at 3:24
  • You can use Skeleton components. When the props is undefined, just show the skeletons and when the fetching is complete, so the data. This way it will be more user friendly. Commented Oct 1, 2020 at 10:32

1 Answer 1

2

Your implementation is close to what I would do. I think that the best solution is to initially render a component that indicates to the user that data is being fetched from the server. Once that data comes back, you can update the state of your parent component, which will case the child component to render instead. A potential solution might look something like this:

function renderChildComponent() {
    const {user} = this.state;

    if (user) {
        return <Child user={user} />;
    }

    return <Loading />;
}

export default class Parent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            user: undefined
        };

    }

    componentDidMount() {
        fetchData(response => {
            this.setState({user: response});
        });
    }

    render() {
        return (
            <div>
                {renderChildComponent.call(this)}
            </div>
        );
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Or put the renderChildComponent() in the Parent component and call it like {this.renderChildComponent()}
Yes, both are valid options, but doing so would make that function publicly accessible from the component class - one could import this component in another file, instantiate the component like so: const parentComponent = React.createElement(Parent);, and call that function like parentComponent.renderChildComponent();. Since there is really no reason to make this function publicly accessible, one should probably err on the side of not doing so.
renderChildComponent code could be within render. The code is much more readable.
I disagree that it would be more readable inside of the render function, but to each their own.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.