tutorial react instalar hello example español ejemplos javascript reactjs

javascript - instalar - react js installation



¿Reacciona el código "después de renderizar"? (14)

Tengo una aplicación donde necesito establecer la altura de un elemento (digamos "contenido de la aplicación") dinámicamente. Toma la altura del "cromo" de la aplicación y la resta y luego establece la altura del "contenido de la aplicación" para que se ajuste al 100% dentro de esas restricciones. Esto es súper simple con las vistas vanilla JS, jQuery o Backbone, pero estoy luchando por descubrir cuál sería el proceso correcto para hacer esto en React.

A continuación se muestra un componente de ejemplo. Quiero poder configurar la altura del app-content para que sea el 100% de la ventana menos el tamaño de ActionBar y BalanceBar , pero ¿cómo sé cuándo se representa todo y dónde colocaría el material de cálculo en esta clase de reacción? ?

/** @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;


De la documentación de ReactDOM.render() :

Si se proporciona la devolución de llamada opcional, se ejecutará después de que el componente se procese o actualice.


Después de renderizar, puede especificar la altura como se muestra a continuación y puede especificar la altura a los componentes de reacción correspondientes.

render: function () { var style1 = {height: ''100px''}; var style2 = { height: ''100px''}; //window. height actually will get the height of the window. var hght = $(window).height(); var style3 = {hght - (style1 + style2)} ; return ( <div className="wrapper"> <Sidebar /> <div className="inner-wrapper"> <ActionBar style={style1} title="Title Here" /> <BalanceBar style={style2} balance={balance} /> <div className="app-content" style={style3}> <List items={items} /> </div> </div> </div> );` }

o puede especificar la altura de cada componente de reacción usando sass. Especifique los primeros 2 componentes principales del componente de reacción con ancho fijo y luego la altura del tercer componente principal del componente con auto. Entonces, según el contenido del tercer div, se asignará la altura.


En mi experiencia, window.requestAnimationFrame no fue suficiente para garantizar que el DOM se haya procesado completamente / reflujo completo desde componentDidMount . Tengo un código en ejecución que accede al DOM inmediatamente después de una llamada componentDidMount y que usa únicamente window.requestAnimationFrame daría como resultado que el elemento esté presente en el DOM; sin embargo, las actualizaciones de las dimensiones del elemento aún no se reflejan ya que aún no se ha producido un reflujo.

La única forma verdaderamente confiable para que esto funcionara fue envolver mi método en un setTimeout y una window.requestAnimationFrame para garantizar que la pila de llamadas actual de React se window.requestAnimationFrame antes de registrarse para el procesamiento del siguiente marco.

function onNextFrame(callback) { setTimeout(function () { requestAnimationFrame(callback) }) }

Si tuviera que especular sobre por qué ocurre esto / es necesario, podría ver Reaccionar actualizaciones de DOM por lotes y no aplicar los cambios al DOM hasta que se complete la pila actual.

En última instancia, si está utilizando mediciones DOM en el código que está disparando después de las devoluciones de llamada React, es probable que desee utilizar este método.


En realidad, estoy teniendo problemas con un comportamiento similar, renderizo un elemento de video en un Componente con su atributo de identificación, por lo que cuando RenderDOM.render () finaliza, carga un complemento que necesita la identificación para encontrar el marcador de posición y no lo encuentra.

El setTimeout con 0ms dentro del componenteDidMount () lo arregló :)

componentDidMount() { if (this.props.onDidMount instanceof Function) { setTimeout(() => { this.props.onDidMount(); }, 0); } }


Para mí, ninguna combinación de window.requestAnimationFrame o setTimeout produjo resultados consistentes. A veces funcionó, pero no siempre, o a veces sería demasiado tarde.

Lo arreglé haciendo loop window.requestAnimationFrame tantas veces como sea necesario.
(Típicamente 0 o 2-3 veces)

La clave es diff > 0 : aquí podemos asegurarnos exactamente cuando la página se actualice.

// Ensure new image was loaded before scrolling if (oldH > 0 && images.length > prevState.images.length) { (function scroll() { const newH = ref.scrollHeight; const diff = newH - oldH; if (diff > 0) { const newPos = top + diff; window.scrollTo(0, newPos); } else { window.requestAnimationFrame(scroll); } }()); }


Puede cambiar el estado y luego hacer sus cálculos en la devolución de llamada setState . Según la documentación de React, "se garantiza que se activará después de que se haya aplicado la actualización".

Esto debe hacerse en componentDidMount o en otro lugar del código (como en un controlador de eventos de cambio de tamaño) en lugar de hacerlo en el constructor.

Esta es una buena alternativa a window.requestAnimationFrame y no tiene los problemas que algunos usuarios han mencionado aquí (es necesario combinarlo con setTimeout o llamarlo varias veces). Por ejemplo:

class AppBase extends React.Component { state = { showInProcess: false, size: null }; componentDidMount() { this.setState({ showInProcess: true }, () => { this.setState({ showInProcess: false, size: this.calculateSize() }); }); } render() { const appStyle = this.state.showInProcess ? { visibility: ''hidden'' } : null; return ( <div className="wrapper"> ... <div className="app-content" style={appStyle}> <List items={items} /> </div> ... </div> ); } }


React tiene pocos métodos de ciclo de vida que ayudan en estas situaciones, las listas incluyen, entre otras, getInitialState, getDefaultProps, componentWillMount, componentDidMount, etc.

En su caso y los casos que deben interactuar con los elementos DOM, debe esperar hasta que el dom esté listo, por lo tanto, use componentDidMount como se muestra a continuación:

/** @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({ componentDidMount: function() { ReactDOM.findDOMNode(this).height = /* whatever HEIGHT */; }, 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;

También para obtener más información sobre el ciclo de vida en reaccionar, puede consultar el siguiente enlace: https://facebook.github.io/react/docs/state-and-lifecycle.html


Siento que esta solución está sucia, pero aquí vamos:

componentDidMount() { this.componentDidUpdate() } componentDidUpdate() { // A whole lotta functions here, fired after every render. }

Ahora me voy a sentar aquí y esperar los votos negativos.


Solo para actualizar un poco esta pregunta con los nuevos métodos de gancho, simplemente puede usar el gancho useEffect :

import React, { useEffect } from ''react'' export default function App(props) { useEffect(() => { // your post layout code (or ''effect'') here. ... }, // array of variables that can trigger an update if they change. Pass an // an empty array if you just want to run it once after component mounted. []) }

Además, si desea ejecutar antes del montaje de diseño, use el useLayoutEffect :

import React, { useLayoutEffect } from ''react'' export default function App(props) { useLayoutEffect(() => { // your pre layout code (or ''effect'') here. ... }, []) }


Tuve el mismo problema.

En la mayoría de los escenarios, el uso de hack-ish setTimeout(() => { }, 0) en componentDidMount() funcionó.

Pero no en un caso especial; y no quería usar ReachDOM findDOMNode ya que la documentación dice:

Nota: findDOMNode es una trampilla de escape utilizada para acceder al nodo DOM subyacente. En la mayoría de los casos, se desaconseja el uso de esta trampilla de escape porque perfora la abstracción del componente.

(Fuente: findDOMNode )

Entonces, en ese componente en particular, tuve que usar el evento componentDidUpdate() , por lo que mi código terminó siendo así:

componentDidMount() { // feel this a little hacky? check this: http://.com/questions/26556436/react-after-render-code setTimeout(() => { window.addEventListener("resize", this.updateDimensions.bind(this)); this.updateDimensions(); }, 0); }

Y entonces:

componentDidUpdate() { this.updateDimensions(); }

Finalmente, en mi caso, tuve que eliminar el oyente creado en componentDidMount :

componentWillUnmount() { window.removeEventListener("resize", this.updateDimensions.bind(this)); }


Tuve una situación extraña cuando necesito imprimir un componente de reacción que recibe una gran cantidad de datos y pintar en el lienzo. He probado todos los enfoques mencionados, ninguno de ellos funcionó de manera confiable para mí, con requestAnimationFrame dentro de setTimeout obtengo un lienzo vacío en el 20% del tiempo, así que hice lo siguiente:

nRequest = n => range(0,n).reduce( (acc,val) => () => requestAnimationFrame(acc), () => requestAnimationFrame(this.save) );

Básicamente hice una cadena de requestAnimationFrame''s, no estoy seguro de si es una buena idea o no, pero hasta ahora funciona en el 100% de los casos (estoy usando 30 como valor para n variable).


Un poco de actualización con las clases de ES6 lugar de React.createClass

import React, { Component } from ''react''; class SomeComponent extends Component { constructor(props) { super(props); // this code might be called when there is no element avaliable in `document` yet (eg. initial render) } componentDidMount() { // this code will be always called when component is mounted in browser DOM (''after render'') } render() { return ( <div className="component"> Some Content </div> ); } }

Además, verifique los métodos del ciclo de vida del componente React: el ciclo de vida del componente

Cada componente tiene muchos métodos similares a componentDidMount por ejemplo.

  • componentWillUnmount() : el componente está a punto de eliminarse del DOM del navegador

Una desventaja de usar componentDidUpdate , o componentDidMount es que en realidad se ejecutan antes de que se dibujen los elementos dom, pero después de que se hayan pasado de React al DOM del navegador.

Digamos, por ejemplo, si necesita establecer node.scrollHeight en el node.scrollTop representado, entonces los elementos DOM de React pueden no ser suficientes. Debe esperar hasta que los elementos terminen de pintarse para obtener su altura.

Solución:

Use requestAnimationFrame para asegurarse de que su código se ejecute después de pintar su objeto recién renderizado

scrollElement: function() { //store a this ref, and var _this = this; //wait for a paint to do scrolly stuff window.requestAnimationFrame(function() { var node = _this.getDOMNode(); if (node !== undefined) { //and scroll them! node.scrollTop = node.scrollHeight; } }); }, componentDidMount: function() { this.scrollElement(); }, // and or componentDidUpdate: function() { this.scrollElement(); }, // and or render: function() { this.scrollElement() return [...]


componentDidMount()

Este método se llama una vez después de que se representa su componente. Entonces su código se vería así.

var AppBase = React.createClass({ componentDidMount: function() { var $this = $(ReactDOM.findDOMNode(this)); // set el height and width etc. }, 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> ); } });