496 Stimmen

Rerender-Ansicht beim Browser-Größenänderung mit React

Wie kann ich React dazu bringen, die Ansicht neu zu rendnern, wenn das Browserfenster neu skaliert wird?

Hintergrund

Ich habe einige Blöcke, die ich individuell auf der Seite anordnen möchte, aber ich möchte auch, dass sie sich ändern, wenn sich das Browserfenster ändert. Das Endergebnis wird letztendlich etwas ähnliches wie Ben Hollands Pinterest Layout sein, jedoch geschrieben in React und nicht nur jQuery. Ich bin noch weit davon entfernt.

Code

Hier ist meine App:

var MyApp = React.createClass({
  //führt das http get vom Server aus
  loadBlocksFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      mimeType: 'textPlain',
      success: function(data) {
        this.setState({data: data.events});
      }.bind(this)
    });
  },
  getInitialState: function() {
    return {data: []};
  },
  componentWillMount: function() {
    this.loadBlocksFromServer();

  },    
  render: function() {
    return (

    );
  }
});

React.renderComponent(
  ,
  document.getElementById('view')
)

Dann habe ich das Block Komponente (entspricht einem Pin im obigen Pinterest Beispiel):

var Block = React.createClass({
  render: function() {
    return (

        {this.props.title}
        {this.props.children}

    );
  }
});

und die Liste/Kollektion von Blocks:

var Blocks = React.createClass({

  render: function() {

    //Ich habe vorübergehend Code, der eine zufällige Position zuweist
    //Siehe innerhalb der folgenden Funktion...

    var blockNodes = this.props.data.map(function (block) {   
      //temporäre zufällige Position
      var topOffset = Math.random() * $(window).width() + 'px'; 
      var leftOffset = Math.random() * $(window).height() + 'px'; 
      return {block.description};   
    });

    return (
        {blockNodes}
    );
  }
});

Frage

Sollte ich das window resize von jQuery hinzufügen? Wenn ja, wo?

$( window ).resize(function() {
  // Komponente neu rendern
});

Gibt es eine "React"-artige Möglichkeit, dies zu tun?

1voto

rahulfaujdar Punkte 317

Versuchen Sie dies :-

resize = () => this.forceUpdate()

componentDidMount() {
  window.addEventListener('resize', this.resize)
}

componentWillUnmount() {
  window.removeEventListener('resize', this.resize)
}

0voto

Elyasaf755 Punkte 753

Für alle, die Typescript-Unterstützung suchen, habe ich den unten stehenden Hook basierend auf der Antwort von @Lead Developer geschrieben:

import { useState, useEffect } from 'react';

export const debounce = (callback: (...args: A) => unknown, msDelay: number) => {
    let timer: NodeJS.Timeout | undefined;

    return (...args: A) => {
        clearTimeout(timer);

        timer = setTimeout(() => {
            timer = undefined;
            callback(...args);
        }, msDelay);
    };
};

export const useWindowDimension = (msDelay = 100) => {
    const [dimension, setDimension] = useState({
        width: window.innerWidth,
        height: window.innerHeight,
    });

    useEffect(() => {
        const resizeHandler = () => {
            setDimension({
                width: window.innerWidth,
                height: window.innerHeight
            });
        };

        const handler = msDelay <= 0 ? resizeHandler : debounce(resizeHandler, msDelay);

        window.addEventListener('resize', handler);

        return () => window.removeEventListener('resize', handler);
    }, []);

    return dimension;
};

export type Dimension = ReturnType;

Das Gute ist natürlich die Typescript-Unterstützung, aber auch die Möglichkeit, die Verzögerungszeit (in ms) zu steuern, die standardmäßig auf 100ms festgelegt ist. Wenn die Verzögerungszeit 0 oder weniger beträgt, wird der Handler nicht verzögert.
Ein weiterer Unterschied besteht darin, dass der Hook ein Objekt vom Typ Dimension zurückgibt, das ist:

type Dimension = {
    width: number;
    height: number;
}

So ist für alle klar, was der Hook tatsächlich zurückgibt.

0voto

Alguem Meugla Punkte 59

In index.js:

function render() {
  ReactDOM.render(, document.getElementById('root'));
}

render();

window.addEventListener('resize', render);

Das erneute Rendern zwingt dazu, alles neu zu berechnen, was von Variablen abhängt, die von React nicht selbst erkannt werden, wie z.B. window.innerWidth/innerHeight, localStorage, etc., während der App-Zustand gleich bleibt.

Wenn es in anderen Situationen notwendig ist, erneut zu rendern, kann diese render() Funktion auch exportiert und an anderen Stellen verwendet werden.

I'm not sure about the impact of this on performace though (as it may be re-rendering everything or just what changed), but for me it seems fast enough when resizing.

0voto

tannerman Punkte 470
import React, {useState} from 'react';

type EventListener = () => void
let eventListener: EventListener | undefined;

function setEventListener(updateSize: (size: number[]) => void){
    if(eventListener){
        window.removeEventListener('resize',eventListener);
    }
    eventListener = () => updateSize([window.innerWidth, window.innerHeight]);

    return eventListener as EventListener;
}

function setResizer(updateSize: (size: number[]) => void) {
    window.addEventListener(
        'resize',
        setEventListener(updateSize)
    );
}

function useWindowSizeTableColumns() {
    const [size, setSize] = useState([
        window.innerWidth || 0,
        window.innerHeight || 0
    ]);

    setResizer(updateSize);

    return size;

    function updateSize(s: number[]) {
        if(size.some((v, i) => v !== s[i])){
            setSize(s);
        }
    }
}

export default useWindowSize;

0voto

Aus diesem Grund ist es besser, wenn Sie diese Daten aus einer CSS- oder JSON-Datei verwenden und dann mit diesen Daten einen neuen Zustand mit this.setState({width: "ein Wert", height: "ein Wert"}) einstellen oder Code schreiben, der Daten zur Bildschirmbreite selbst verwendet, wenn Sie möchten, dass Bilder responsiv angezeigt werden.

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