Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I block a React component to be rendered until I fetched all informations?

I need to fetch some informations before rendering my component. The information will be provided by an API and fetched with an ajax call.

I'm just trying to wait 10 seconds before rendering my component but it says:

Uncaught Invariant Violation: Login.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.

Can i render my component after the fulfilment of a promise?

/** Page Login */ class Login extends React.Component {    /**    * @constructor    * @param {object} props La fonction super() appelle le parent pour y transmettre ses propriétés    */   constructor(props) {     super(props);      this.handleFormSubmit = this.handleFormSubmit.bind(this);   }    /**    * Reçoit les valeurs des formulaires    */   handleFormSubmit(data) {     const { dispatch } = this.props;      dispatch(fetchLoginAuth(data));   }    normalRender() {     return (       <div id="login-page">         <div className="container-fluid">           <div className="row">             <div className="col-md-2">               <Link to="/" className="home-link"><img src={BASE_URL + '/assets/img/logo.svg'} alt="Logo" /></Link>             </div>           </div>           <div className="row">             <div className="col-lg-4 col-lg-offset-4">               <h1><FormattedMessage {...messages.loginPageTitle} /></h1>             </div>           </div>           {React.cloneElement(this.props.children || <div />, { onSubmit: this.handleFormSubmit, login: this.props.login })}         </div>       </div>     );   }    /**    * Render le component - ReactTransitionGroup    * @return {JSX} Rend la page Registration    */   render() {     setTimeout(this.normalRender, 10000);   } } 

I use ES6 with JSX, redux, an universal router with react-router.

Thank you very much for your help!

like image 277
Crak_mboutin Avatar asked Jan 26 '16 20:01

Crak_mboutin


People also ask

How do you prevent a component from rendering in React?

1. Memoization using useMemo() and UseCallback() Hooks. Memoization enables your code to re-render components only if there's a change in the props. With this technique, developers can avoid unnecessary renderings and reduce the computational load in applications.

How do you restrict a component in React?

To restrict access to routes in React Router, we set the render prop to a function that renders the component we want according to the condition we're checking. import { Route, Redirect } from "react-router"; <Route exact path="/" render={() => (loggedIn ?

How do you prevent a child component from rendering?

memo() If you're using a React class component you can use the shouldComponentUpdate method or a React. PureComponent class extension to prevent a component from re-rendering.

Can you React component without rendering?

Nope, render() method can't return an empty array or anything other than other React component.


1 Answers

Here's what I do normally:

class Login extends React.Component {     constructor(props) {         //IMPLEMENT OTHER JUNK HERE         this.state = {             data: null //This is what our data will eventually be loaded into         };     }     componentDidMount() {         this.loadData();     }     loadData() {         /*LOAD DATA, INSERT BELOW LINE IN CALLBACK FUNCTION             this.setState({                 data: //LOADED DATA             });         */     }     render() {         if (!this.state.data) {             return <div />         }          //WE HAVE DATA, DO A NORMAL RENDER         return (             <div id="login-page">                 <div className="container-fluid">                     <div className="row">                         <div className="col-md-2">                             <Link to="/" className="home-link"><img src={BASE_URL + '/assets/img/logo.svg'} alt="Logo" /></Link>                         </div>                     </div>                     <div className="row">                         <div className="col-lg-4 col-lg-offset-4">                             <h1><FormattedMessage {...messages.loginPageTitle} /></h1>                         </div>                     </div>                     {React.cloneElement(this.props.children || <div />, { onSubmit: this.handleFormSubmit, login: this.props.login })}                 </div>             </div>         );     } } 

Here's a breakdown of what is going to happen...

  1. Component is going to load
  2. componentDidMount() fires, runs loadData()
  3. loadData() starts ajax request, returns before ajax request returns data because we love asynchronous data loads
  4. render() runs. Since this.state.data is null, we have pass into the if block, and <div /> is returned.
  5. Ajax data load finishes, and a this.setState() call is made, which forces a re-render.
  6. render() runs again. Since this.state.data contains a value now, we skip over the if block and render our normal stuff.

Edit (11 Oct 2019): Migrated componentWillMount() to componentDidMount()

like image 171
molson504x Avatar answered Sep 23 '22 03:09

molson504x