482 Stimmen

React "nach dem Rendern" Code?

I have an app where I need to set the height of an element (lets say "app-content") dynamically. It takes the height of the "chrome" of the app and subtracts it and then sets the height of the "app-content" to fit 100% within those constraints. This is super simple with vanilla JS, jQuery, or Backbone views, but I'm struggling to figure out what the right process would be for doing this in React?

Below is an example component. I want to be able to set app-content's height to be 100% of the window minus the size of the ActionBar and BalanceBar, but how do I know when everything is rendered and where would I put the calculation stuff in this React Class?

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

    );
  }
});

module.exports = AppBase;

14voto

Jaakko Karhu Punkte 2268

Ich fühle, dass diese Lösung schmutzig ist, aber hier gehen wir:

componentDidMount() {
    this.componentDidUpdate()
}

componentDidUpdate() {
    // Eine Menge Funktionen hier, die nach jedem Rendern ausgeführt werden.
}

Jetzt werde ich hier nur sitzen und auf die Daumen runter warten.

12voto

Alireza Punkte 92209

React hat einige Lifecycle-Methoden, die in solchen Situationen helfen, die Listen, einschließlich, aber nicht beschränkt auf getInitialState, getDefaultProps, componentWillMount, componentDidMount usw.

In Ihrem Fall und in den Fällen, die mit den DOM-Elementen interagieren müssen, müssen Sie warten, bis der DOM bereit ist. Verwenden Sie also componentDidMount wie folgt:

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

    );
  }
});

module.exports = AppBase;

Auch für weitere Informationen zu Lifecycle in React können Sie den untenstehenden Link besuchen: https://facebook.github.io/react/docs/state-and-lifecycle.html

getInitialState, getDefaultProps, componentWillMount, componentDidMount

9voto

theRonny Punkte 375

Ich bin auf das gleiche Problem gestoßen.

In den meisten Szenarien hat der hackige setTimeout(() => { }, 0) in componentDidMount() funktioniert.

Aber nicht in einem speziellen Fall; und ich wollte nicht ReachDOM findDOMNode verwenden, da die Dokumentation sagt:

Hinweis: findDOMNode ist ein Ausweg, um auf das zugrunde liegende DOM zuzugreifen. In den meisten Fällen wird die Verwendung dieses Auswegs nicht empfohlen, weil es die Komponentenabstraktion durchbricht.

(Quelle: findDOMNode)

Also musste ich in diesem speziellen Fall das componentDidUpdate() Ereignis verwenden, sodass mein Code schließlich so aussah:

componentDidMount() {
    // fühlt sich das ein bisschen hacky an? schau hier nach: http://stackoverflow.com/questions/26556436/react-after-render-code
    setTimeout(() => {
       window.addEventListener("resize", this.updateDimensions.bind(this));
       this.updateDimensions();
    }, 0);
}

Und dann:

componentDidUpdate() {
    this.updateDimensions();
}

Schließlich musste ich in meinem Fall den in componentDidMount erstellten Listener entfernen:

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

6voto

Farantir Punkte 61

Es gibt tatsächlich eine einfachere und sauberere Version als die Verwendung von requestAnimationFrame oder Timeouts. Ich bin überrascht, dass niemand darauf hingewiesen hat: den Vanilla-JS-Onload-Handler. Wenn möglich, verwenden Sie componentDidMount. Wenn nicht, binden Sie einfach eine Funktion am onload-Handler des JSX-Komponenten. Wenn Sie möchten, dass die Funktion bei jedem Rendern ausgeführt wird, führen Sie sie auch vor dem Zurückgeben Ihrer Ergebnisse in der Render-Funktion aus. Der Code würde so aussehen:

runAfterRender = () => 
{
  const myElem = document.getElementById("myElem")
  if(myElem)
  {
    //wichtige Dinge ausführen
  }
}

render()
{
  this.runAfterRender()
  return (

      //mehr Dinge

  )
}

}

4voto

Barceyken Punkte 95

Ich habe tatsächlich ein Problem mit einem ähnlichen Verhalten, ich rendere ein Video-Element in einem Component mit seinem id-Attribut, sodass, wenn RenderDOM.render() endet, ein Plugin geladen wird, das die id benötigt, um den Platzhalter zu finden, und es nicht finden kann.

Das setTimeout mit 0 ms innerhalb des componentDidMount() hat es behoben :)

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X