Réagir “après un rendu” code?
J'ai une application dans laquelle j'ai besoin de régler la hauteur d'un élément (permet de dire "app-contenu") de manière dynamique. Il prend la hauteur de la "google chrome" de l'application et de la soustraction et puis définit la hauteur de la "app-contenu" pour s'adapter à 100% à l'intérieur de ces contraintes. C'est super simple à la vanille, JS, jQuery, ou épine Dorsale de vues, mais j'ai du mal à comprendre ce que le processus de droite serait pour le faire dans de Réagir?
Ci-dessous est un exemple de composant. Je veux être en mesure de définir app-content
hauteur de 100% de la fenêtre moins la taille de la ActionBar
et BalanceBar
, mais comment puis-je savoir quand tout est rendu et où aurais-je mis le calcul des trucs dans ce Réagir la Classe?
/** @jsx React.DOM */
var List = require('../list');
var ActionBar = require('../action-bar');
var BalanceBar = require('../balance-bar');
var Sidebar = require('../sidebar');
var AppBase = React.createClass({
render: function () {
return (
<div className="wrapper">
<Sidebar />
<div className="inner-wrapper">
<ActionBar title="Title Here" />
<BalanceBar balance={balance} />
<div className="app-content">
<List items={items} />
</div>
</div>
</div>
);
}
});
module.exports = AppBase;
- Dans les navigateurs modernes vous pouvez utiliser flexbox de faire mieux. Sinon Harborhoffer de réponse.
- Au début, j'étais comme "comment flexbox résoudre ce problème?" puis je me suis souvenu de la colonne en fonction de Flexbox et cela a fonctionné comme un charme!
Vous devez vous connecter pour publier un commentaire.
https://facebook.github.io/react/docs/react-component.html#componentdidmount
Cette méthode est appelée une fois après votre composant est rendu. Si votre code devrait ressembler alors.
componentDidUpdate
si les valeurs peuvent changer après la première de rendre.componentDidMount()
ne cause pas une transition.componentDidMount: () => { setTimeout(addClassFunction())}
, ou de l'utilisation de la rAF, la réponse ci-dessous cela donne cette réponse.Un inconvénient de l'utilisation de
componentDidUpdate
, oucomponentDidMount
est qu'ils sont réellement exécutées avant les éléments dom sont fait d'être attiré, mais après qu'ils ont été transmis de Réagir à l'explorateur DOM.Disons, par exemple, si vous avez besoin de définir nœud.scrollHeight pour le rendu de nœud.scrollTop, alors Réagir DOM éléments peut ne pas être suffisant. Vous devez attendre jusqu'à ce que les éléments sont en fait être peints pour obtenir leur hauteur.
Solution:
Utilisation
requestAnimationFrame
pour vous assurer que votre code est exécuté après la peinture de votre rendu de l'objetwindow.requestAnimationFrame
de savoir exactement quand le DOM mises à jour: stackoverflow.com/a/50206430/1313757node.addEventListener
avec le type d'événement (par exemple,transitionend
) et avec le{once: true}
paramètre (nous ne voulons appeler cette méthode une fois) a fait le travail pour moi. Pas besoin dewindow.requestAnimationFrame
nisetTimeout
.Dans mon expérience
window.requestAnimationFrame
n'était pas suffisant pour s'assurer que les DOM ont été entièrement rendus /refusion complète decomponentDidMount
. J'ai l'exécution de code qui accède à la DOM immédiatement après uncomponentDidMount
appel et en utilisant uniquementwindow.requestAnimationFrame
conséquence serait l'élément présent dans le DOM; cependant, les mises à jour de l'élément dimensions ne sont pas reflétées pourtant, depuis une redistribution n'a pas encore eu lieu.Le seul véritable moyen fiable pour ce travail était d'envelopper la méthode dans un
setTimeout
et unwindow.requestAnimationFrame
pour assurer Réagir de la pile d'appel en cours est effacée avant de vous inscrire pour la prochaine trame de rendu.Si j'avais à spéculer sur la raison /c'est nécessaire, je pouvais voir Réagir dosage DOM mises à jour et de ne pas appliquer les modifications pour les DOM jusqu'à ce que après la pile en cours est terminée.
En fin de compte, si vous êtes en utilisant DOM mesures dans le code que vous êtes de cuisson après la Réagir rappels, vous aurez probablement envie d'utiliser cette méthode.
0
à setTimeout si vous n'êtes pas en lui donnant un temps.requestAnimationFrame
appel? Par exemple;function onNextFrame(cb) { window.requestAnimationFrame(_ => window.requestAnimationFrame(cb)) }
. Basé sur les spécifications (html.spec.whatwg.org/multipage/webappapis.html#animation-frames), ce qui permettrait de garantir qu'il fonctionne sur l'image suivante, après le premier render (en particulier, de vérifier l'ordre d'exécution de la liste dans "exécuter trame de l'animation de rappel"). Il évite l'ambiguïté de quand setTimeout sera exécuté wrt l'image suivante.componentDidUpdate
.Réagir a quelques du cycle de vie des méthodes qui aident dans ces situations, les listes, y compris mais non limité à getInitialState, getDefaultProps, componentWillMount, componentDidMount etc.
Dans votre cas et les cas qui doit interagir avec les éléments du DOM, vous devez attendre jusqu'à ce que le dom est prêt, afin de l'utiliser componentDidMount comme ci-dessous:
Aussi pour plus d'informations sur le cycle de vie de réagir, vous pouvez avoir regarder le lien ci-dessous:
https://facebook.github.io/react/docs/state-and-lifecycle.html
J'ai l'impression que cette solution est sale, mais ici nous allons:
Maintenant, je vais juste rester ici et attendre pour les votes contre.
Vous pouvez modifier l'état et ensuite faire vos calculs dans le setState de rappel. Selon la Réagir la documentation, c'est "garanti à feu après la mise à jour a été appliquée".
Cela devrait être fait dans
componentDidMount
ou ailleurs dans le code (comme sur un redimensionnement de gestionnaire d'événement) plutôt que dans le constructeur.C'est une bonne alternative à
window.requestAnimationFrame
et il n'a pas de problèmes, certains utilisateurs ont mentionné ici (besoin de le combiner avecsetTimeout
ou l'appeler plusieurs fois). Par exemple:Je suis effectivement avoir un problème avec le même comportement, je le rendu d'un élément vidéo dans un Composant avec son attribut id donc quand RenderDOM.render() se termine, il charge un plugin qui a besoin de l'id de trouver l'emplacement réservé, et il ne parvient pas à le trouver.
Le setTimeout avec 0ms à l'intérieur de la componentDidMount() a fixé 🙂
Juste pour mettre à jour un peu cette question avec le nouveau Crochet méthodes, vous pouvez simplement utiliser la
useEffect
crochet:Aussi, si vous souhaitez exécuter avant la mise en page du mont utiliser le
useLayoutEffect
crochet:Après le rendu, vous pouvez spécifier la hauteur comme ci-dessous et que vous pouvez spécifier la hauteur correspondant à réagir composants.
ou vous pouvez spécifier la hauteur de chaque réagir composant à l'aide de sass. Spécifier les 2 premiers réagir composant principal de div avec une largeur fixe, puis le troisième élément div principale de la hauteur avec l'auto. Sur la base de la troisième div du contenu de la hauteur seront assignés.
De la ReactDOM.render() documentation:
ReactDOM.render
, pas pour le au niveau des composantes duReactElement.render
(qui est le sujet ici).Je suis tombé sur le même problème.
Dans la plupart des scénarios en utilisant le hack-ish
setTimeout(() => { }, 0)
danscomponentDidMount()
travaillé.Mais pas dans un cas particulier; et je ne voulais pas utiliser le
ReachDOM findDOMNode
depuis la documentation dit:(Source: https://facebook.github.io/react/docs/react-dom.html#finddomnode)
Donc, dans ce composant particulier, j'ai dû utiliser le
componentDidUpdate()
de l'événement, de sorte que mon code a fini par être comme ceci:Et puis:
Enfin, dans mon cas, j'ai dû enlever l'écouteur créé en
componentDidMount
:Pour moi, pas de combinaison de
window.requestAnimationFrame
ousetTimeout
à des résultats cohérents. Parfois, cela a fonctionné, mais pas toujours—ou, parfois, il serait trop tard.Je l'ai fixée par boucle
window.requestAnimationFrame
autant de fois que nécessaire.(Généralement 0 ou 2 à 3 fois)
La clé est
diff > 0
: ici, nous pouvons assurer exactement quand la page des mises à jour.J'avais situation bizarre quand j'ai besoin d'imprimer réagir composant qui reçoit une grande quantité de données et la peinture sur toile. J'ai essayé toutes les approches mentionnées, non d'entre eux a travaillé de manière fiable pour moi, avec requestAnimationFrame à l'intérieur de setTimeout je reçois vide toile en 20% du temps, j'ai donc fait la suivante:
Fondamentalement, j'ai fait une chaîne de requestAnimationFrame du, pas sûr, est-ce une bonne idée ou pas, mais cela fonctionne dans 100% des cas pour moi pour l'instant (je suis en utilisant 30 comme une valeur pour n variable).
Un peu de mise à jour avec
ES6
classes au lieu deReact.createClass
Aussi - vérifier Réagir composante du cycle de vie des méthodes: https://facebook.github.io/react/docs/react-component.html#the-component-lifecycle
Tous les composants ont un grand nombre de méthodes similaires à
componentDidMount
par exemple.componentWillUnmount()
- composante est sur le point d'être supprimé à partir du navigateur DOM