Je dois aller chercher des informations avant de rendre mon composant. Les informations seront fournies par une API et récupérées avec un appel ajax.
J'essaie juste d'attendre 10 secondes avant de rendre mon composant, mais il est écrit:
Uncaught Invariant Violation: Login.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.
Puis-je rendre mon composant après avoir rempli une promesse?
/** 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);
}
}
J'utilise ES6 avec JSX, Redux, un routeur universel avec react-router.
Merci beaucoup pour votre aide!
Voici ce que je fais normalement:
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
};
}
componentWillMount() {
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>
);
}
}
Voici un aperçu de ce qui va se passer ...
this.state.data
est null
, nous avons passé dans le bloc if, et <div />
est renvoyé.this.setState()
est effectué, ce qui oblige à effectuer un nouveau rendu.this.state.data
contient une valeur maintenant, nous ignorons le bloc if et rendons nos trucs normaux.Toujours laisser React rendre.
Pendant que vous faites quelque chose d'asynchrone, montrez un spinner de chargement ou quelque chose.
render() {
<div>
{ this.state.isLoading &&
<div>Loading.. please wait!</div>
}
{ !this.state.isLoading &&
<div>My data has arrived!</div>
}
</div>
}
Suspendre le rendu semble hacky ...
Pourquoi ne pas restituer une partie de votre composant avec un sous-composant placeholder ... Puis, lorsque l'appel ajax se termine, déclenchez une action pour modifier l'état et restituer votre composant d'origine.
Ça va être mieux en termes d'expérience utilisateur et d'élégance.
J'aurais juste fait un commentaire sur la première réponse, mais je n'ai pas la réputation.
composantWillMount () est maintenant obsolète. Il est donc préférable de déplacer l'appel loadData vers le constructeur
class Menu extends Component {
state = {}
constructor(props) {
super(props)
loadData().then(data =>
this.setState({data: data})
)
}
async loadData() {
//get your data
}
render() {
if (isEmpty(this.state)) {
return <div>Loading</div>
}
return (
<div id="site-menu">
<section className="site-menu-content">
{data}
</section>
</div>
)
}
Vous pouvez essayer quelque chose comme
/** Page Login */
class Login extends React.Component {
constructor(props) {
...
this.state = {
ready: false
};
}
componentWillMount() {
setTimeout(this.handleLoading, 10000);
}
handleLoading() {
this.setState({ ready: true });
}
render() {
if(!this.state.ready)
return null;
return normalRender();
}
}