programing

React를 사용하여 브라우저 크기 조정 시 보기 다시 렌더링

shortcode 2023. 1. 8. 14:54
반응형

React를 사용하여 브라우저 크기 조정 시 보기 다시 렌더링

브라우저 창의 크기가 변경되었을 때 React를 통해 보기를 다시 렌더링하려면 어떻게 해야 합니까?

배경

페이지에 개별적으로 배치하고 싶은 블록이 몇 개 있습니다만, 브라우저 창이 바뀌면 업데이트해 주셨으면 합니다.최종 결과는 Ben Holland의 Pinterest 레이아웃과 비슷하지만 jQuery뿐만 아니라 React를 사용하여 작성됩니다.난 아직 멀었어.

코드

제 앱은 다음과 같습니다.

var MyApp = React.createClass({
  //does the http get from the server
  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 (
        <div>
      <Blocks data={this.state.data}/>
      </div>
    );
  }
});

React.renderComponent(
  <MyApp url="url_here"/>,
  document.getElementById('view')
)

나는 ★★★★★★★★★★★★★★★★★★★★★★★.Block에 )Pin위의 핀터레스트 예에서는 다음과 같습니다.

var Block = React.createClass({
  render: function() {
    return (
        <div class="dp-block" style={{left: this.props.top, top: this.props.left}}>
        <h2>{this.props.title}</h2>
        <p>{this.props.children}</p>
        </div>
    );
  }
});

</ CHANGE/FONT CHANGE:>/집합Blocks:

var Blocks = React.createClass({

  render: function() {

    //I've temporarily got code that assigns a random position
    //See inside the function below...

    var blockNodes = this.props.data.map(function (block) {   
      //temporary random position
      var topOffset = Math.random() * $(window).width() + 'px'; 
      var leftOffset = Math.random() * $(window).height() + 'px'; 
      return <Block order={block.id} title={block.summary} left={leftOffset} top={topOffset}>{block.description}</Block>;
    });

    return (
        <div>{blockNodes}</div>
    );
  }
});

질문.

jQuery 창 크기를 추가해야 합니까?그렇다면 어디에?

$( window ).resize(function() {
  // re-render the component
});

더 '리액트'한 방법이 있을까요?

리액트 훅 사용:

할 수 .resize이벤트, 다음과 같은 것이 있습니다.

import React, { useLayoutEffect, useState } from 'react';

function useWindowSize() {
  const [size, setSize] = useState([0, 0]);
  useLayoutEffect(() => {
    function updateSize() {
      setSize([window.innerWidth, window.innerHeight]);
    }
    window.addEventListener('resize', updateSize);
    updateSize();
    return () => window.removeEventListener('resize', updateSize);
  }, []);
  return size;
}

function ShowWindowDimensions(props) {
  const [width, height] = useWindowSize();
  return <span>Window size: {width} x {height}</span>;
}

여기서의 장점은 로직이 캡슐화되어 있다는 것입니다.또, 이 Hook은, 윈도우 사이즈를 사용하고 싶은 장소에 관계없이 사용할 수 있습니다.

React 클래스 사용:

수 이됩니다(componentDidMount 등).이 컴포넌트는 윈도우 치수를 표시하기만 하면 됩니다(예:<span>Window size: 1024 x 768</span>

import React from 'react';

class ShowWindowDimensions extends React.Component {
  state = { width: 0, height: 0 };
  render() {
    return <span>Window size: {this.state.width} x {this.state.height}</span>;
  }
  updateDimensions = () => {
    this.setState({ width: window.innerWidth, height: window.innerHeight });
  };
  componentDidMount() {
    window.addEventListener('resize', this.updateDimensions);
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.updateDimensions);
  }
}

@SophieAlpert가 맞습니다.+1. 이 답변을 바탕으로 jQuery를 사용하지 않고 수정한 솔루션을 제공하고 싶습니다.

var WindowDimensions = React.createClass({
    render: function() {
        return <span>{this.state.width} x {this.state.height}</span>;
    },
    updateDimensions: function() {

    var w = window,
        d = document,
        documentElement = d.documentElement,
        body = d.getElementsByTagName('body')[0],
        width = w.innerWidth || documentElement.clientWidth || body.clientWidth,
        height = w.innerHeight|| documentElement.clientHeight|| body.clientHeight;

        this.setState({width: width, height: height});
        // if you are using ES2015 I'm pretty sure you can do this: this.setState({width, height});
    },
    componentWillMount: function() {
        this.updateDimensions();
    },
    componentDidMount: function() {
        window.addEventListener("resize", this.updateDimensions);
    },
    componentWillUnmount: function() {
        window.removeEventListener("resize", this.updateDimensions);
    }
});

매우 심플한 솔루션:

resize = () => this.forceUpdate()

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

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

이것은 jQuery를 사용하지 않고es6를 사용하는 간단한 예입니다.

import React, { Component } from 'react';

export default class CreateContact extends Component {
  state = {
    windowHeight: undefined,
    windowWidth: undefined
  }

  handleResize = () => this.setState({
    windowHeight: window.innerHeight,
    windowWidth: window.innerWidth
  });

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

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

  render() {
    return (
      <span>
        {this.state.windowWidth} x {this.state.windowHeight}
      </span>
    );
  }
}

import React, { useEffect, useState } from "react";

let App = () => {
  const [windowWidth, setWindowWidth] = useState(0);
  const [windowHeight, setWindowHeight] = useState(0);
  let resizeWindow = () => {
    setWindowWidth(window.innerWidth);
    setWindowHeight(window.innerHeight);
  };

  useEffect(() => {
    resizeWindow();
    window.addEventListener("resize", resizeWindow);
    return () => window.removeEventListener("resize", resizeWindow);
  }, []);

  return (
    <div>
      <span>
        {windowWidth} x {windowHeight}
      </span>
    </div>
  );
};

React 16.8부터는 후크를 사용할 수 있습니다!

/* globals window */
import React, { useState, useEffect } from 'react'
import _debounce from 'lodash.debounce'

const Example = () => {
  const [width, setWidth] = useState(window.innerWidth)

  useEffect(() => {
    const handleResize = _debounce(() => setWidth(window.innerWidth), 100)

    window.addEventListener('resize', handleResize);

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

  return <>Width: {width}</>
}

2020년에 갱신.퍼포먼스를 중시하는 리액트 개발자를 위해서.

위의 솔루션은 작동하지만 창 크기가 1픽셀씩 변경될 때마다 컴포넌트를 다시 렌더링합니다.

때문에 가 생기는 경우가 에, 는 이렇게 썼습니다.useWindowDimension을 빼는 resize: : 100ms'

import React, { useState, useEffect } from 'react';

export function useWindowDimension() {
  const [dimension, setDimension] = useState([
    window.innerWidth,
    window.innerHeight,
  ]);
  useEffect(() => {
    const debouncedResizeHandler = debounce(() => {
      console.log('***** debounced resize'); // See the cool difference in console
      setDimension([window.innerWidth, window.innerHeight]);
    }, 100); // 100ms
    window.addEventListener('resize', debouncedResizeHandler);
    return () => window.removeEventListener('resize', debouncedResizeHandler);
  }, []); // Note this empty array. this effect should run only on mount and unmount
  return dimension;
}

function debounce(fn, ms) {
  let timer;
  return _ => {
    clearTimeout(timer);
    timer = setTimeout(_ => {
      timer = null;
      fn.apply(this, arguments);
    }, ms);
  };
}

이렇게 쓰세요.

function YourComponent() {
  const [width, height] = useWindowDimension();
  return <>Window width: {width}, Window height: {height}</>;
}

2018년 편집: React는 컨텍스트를 1등급으로 지원합니다.


저는 이 특정 문제를 대상으로 하지만 더 일반적인 문제를 대상으로 하는 일반적인 답변을 드리려고 합니다.

부작용에 신경 안 쓴다면 팩커리 같은 을 사용하면 된다.

플럭스를 사용하는 경우 윈도우 특성을 포함하는 스토어를 작성하여 매번 윈도우 객체를 조회하지 않고도 순수 렌더 함수를 유지할 수 있습니다.

응답성이 뛰어난 웹 사이트를 구축하고 싶지만 미디어 쿼리보다 리액트인라인 스타일을 선호하거나 창 너비에 따라 HTML/JS 동작을 변경하는 경우에는 다음을 계속 읽어 보십시오.

리액트 컨텍스트란 무엇이며, 이 컨텍스트에 대해 말하는 이유

React 컨텍스트는 퍼블릭 API에 없으며 컴포넌트의 전체 계층에 속성을 전달할 수 있습니다.

리액트 콘텍스트는 특히 앱 전체에 절대 변하지 않는 것을 전달하는데 유용합니다(많은 플럭스 프레임워크에서 믹스인을 통해 사용됩니다).앱 비즈니스 불변수(접속된 userId 등)를 저장하여 어디서나 사용할 수 있습니다.

그러나 그것은 또한 바뀔 수 있는 것들을 저장하는데도 사용될 수 있다.문제는 콘텍스트가 변경되면 콘텍스트를 사용하는 모든 컴포넌트를 재렌더링해야 하며, 그렇게 하는 것이 쉽지 않다는 것입니다.최적의 해결책은 대부분의 경우 새로운 콘텍스트를 사용하여 앱 전체를 마운트 해제/재마운트하는 것입니다.forceUpdate는 재귀적이지 않습니다.

아시다시피 컨텍스트는 실용적이지만 변경 시 퍼포먼스에 영향이 있으므로 너무 자주 변경해서는 안 됩니다.

문맥에 넣는 내용

  • 불변성: 연결된 userId, 세션 등토큰이든 뭐든...
  • 자주 변하지 않는 것

다음은 자주 변경되지 않는 사항입니다.

현재 사용자 언어:

자주 바뀌는 것은 아닙니다.또, 변경되면, 앱 전체가 번역되기 때문에, 모든 것을 재렌더 할 필요가 있습니다.핫 랭귀지 변경의 매우 좋은 사용 예입니다.

창 속성

폭과 높이는 자주 변하지 않지만, 레이아웃과 동작은 조정해야 할 수 있습니다.레이아웃의 경우 CSS 미디어 쿼리를 사용하여 쉽게 커스터마이즈할 수 있지만 그렇지 않을 수도 있고 다른 HTML 구조를 필요로 할 수도 있습니다.동작에 대해서는 Javascript로 대응해야 합니다.

모든 크기 조정 이벤트에서 모든 항목을 다시 렌더링할 필요는 없으므로 크기 조정 이벤트를 디버전해야 합니다.

당신의 문제는 화면 폭에 따라 몇 개의 아이템을 표시해야 하는지 알고 싶다는 것입니다.따라서 먼저 응답 중단점을 정의하고 사용할 수 있는 다양한 레이아웃 유형의 수를 열거해야 합니다.

예를 들어 다음과 같습니다.

  • 레이아웃 "1col", 너비 <= 600인 경우
  • 레이아웃 "2col", 600 < 폭 < 1000의 경우
  • 레이아웃 "3col", 1000 <= 폭일 경우

크기 조정 이벤트(디버깅됨)에서는 창 개체를 쿼리하여 현재 레이아웃 유형을 쉽게 가져올 수 있습니다.

그런 다음 레이아웃 유형을 이전 레이아웃 유형과 비교할 수 있습니다. 변경된 경우 새 컨텍스트로 앱을 다시 렌더링합니다. 이렇게 하면 사용자가 크기 조정 이벤트를 트리거했지만 실제로 레이아웃 유형이 변경되지 않았으므로 필요한 경우에만 다시 렌더링할 수 있습니다.

일단 그것을 가지고 있으면, HTML, 동작, CSS 클래스를 커스터마이즈 할 수 있도록, 앱내의 레이아웃 타입(콘텍스트를 개입시켜 액세스 가능)을 간단하게 사용할 수 있습니다.리액트 렌더 기능 내에서 레이아웃 유형을 알 수 있으므로 인라인 스타일을 사용하여 응답성이 뛰어난 웹 사이트를 안전하게 작성할 수 있으며 미디어 쿼리가 전혀 필요하지 않습니다.

플럭스를 사용하면 리액트 콘텍스트 대신 스토어를 사용할 수 있지만, 앱에 반응하는 컴포넌트가 많으면 콘텍스트를 사용하는 것이 더 간단하지 않을까요?

@senornestor의 솔루션을 사용하고 있습니다만, 완전히 올바르게 하려면 이벤트청취자도 삭제해야 합니다.

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

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

handleResize = () => {
    this.forceUpdate();
};

그렇지 않으면 다음과 같은 경고가 표시됩니다.

경고: forceUpdate(...): 마운트 또는 마운트 구성 요소만 업데이트할 수 있습니다.이는 보통 마운트 해제된 컴포넌트에서 forceUpdate()를 호출했음을 의미합니다.이건 수술 금지야XXX 컴포넌트의 코드를 확인해 주세요.

생략하고, 하겠습니다.react-dimensions상위 컴포넌트

https://github.com/digidem/react-dimensions

간단한 추가만 하면 됩니다.import 함수 호출을 ""에 액세스할 수 .this.props.containerWidth ★★★★★★★★★★★★★★★★★」this.props.containerHeight이치노

// Example using ES6 syntax
import React from 'react'
import Dimensions from 'react-dimensions'

class MyComponent extends React.Component {
  render() (
    <div
      containerWidth={this.props.containerWidth}
      containerHeight={this.props.containerHeight}
    >
    </div>
  )
}

export default Dimensions()(MyComponent) // Enhanced component

이 코드는 새로운 React 컨텍스트 API를 사용하고 있습니다.

  import React, { PureComponent, createContext } from 'react';

  const { Provider, Consumer } = createContext({ width: 0, height: 0 });

  class WindowProvider extends PureComponent {
    state = this.getDimensions();

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

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

    getDimensions() {
      const w = window;
      const d = document;
      const documentElement = d.documentElement;
      const body = d.getElementsByTagName('body')[0];
      const width = w.innerWidth || documentElement.clientWidth || body.clientWidth;
      const height = w.innerHeight || documentElement.clientHeight || body.clientHeight;

      return { width, height };
    }

    updateDimensions = () => {
      this.setState(this.getDimensions());
    };

    render() {
      return <Provider value={this.state}>{this.props.children}</Provider>;
    }
  }

그런 다음 코드로 원하는 장소에서 다음과 같이 사용할 수 있습니다.

<WindowConsumer>
  {({ width, height }) =>  //do what you want}
</WindowConsumer>

이것이 최선의 방법인지는 모르겠지만, 저는 처음에 스토어를 만들고 WindowStore라고 불렀습니다.

import {assign, events} from '../../libs';
import Dispatcher from '../dispatcher';
import Constants from '../constants';

let CHANGE_EVENT = 'change';
let defaults = () => {
    return {
        name: 'window',
        width: undefined,
        height: undefined,
        bps: {
            1: 400,
            2: 600,
            3: 800,
            4: 1000,
            5: 1200,
            6: 1400
        }
    };
};
let save = function(object, key, value) {
    // Save within storage
    if(object) {
        object[key] = value;
    }

    // Persist to local storage
    sessionStorage[storage.name] = JSON.stringify(storage);
};
let storage;

let Store = assign({}, events.EventEmitter.prototype, {
    addChangeListener: function(callback) {
        this.on(CHANGE_EVENT, callback);
        window.addEventListener('resize', () => {
            this.updateDimensions();
            this.emitChange();
        });
    },
    emitChange: function() {
        this.emit(CHANGE_EVENT);
    },
    get: function(keys) {
        let value = storage;

        for(let key in keys) {
            value = value[keys[key]];
        }

        return value;
    },
    initialize: function() {
        // Set defaults
        storage = defaults();
        save();
        this.updateDimensions();
    },
    removeChangeListener: function(callback) {
        this.removeListener(CHANGE_EVENT, callback);
        window.removeEventListener('resize', () => {
            this.updateDimensions();
            this.emitChange();
        });
    },
    updateDimensions: function() {
        storage.width =
            window.innerWidth ||
            document.documentElement.clientWidth ||
            document.body.clientWidth;
        storage.height =
            window.innerHeight ||
            document.documentElement.clientHeight ||
            document.body.clientHeight;
        save();
    }
});

export default Store;

그런 다음 내 부품에 이런 식으로 저장해놨어

import WindowStore from '../stores/window';

let getState = () => {
    return {
        windowWidth: WindowStore.get(['width']),
        windowBps: WindowStore.get(['bps'])
    };
};

export default React.createClass(assign({}, base, {
    getInitialState: function() {
        WindowStore.initialize();

        return getState();
    },
    componentDidMount: function() {
        WindowStore.addChangeListener(this._onChange);
    },
    componentWillUnmount: function() {
        WindowStore.removeChangeListener(this._onChange);
    },
    render: function() {
        if(this.state.windowWidth < this.state.windowBps[2] - 1) {
            // do something
        }

        // return
        return something;
    },
    _onChange: function() {
        this.setState(getState());
    }
}));

참고로, 이 파일들은 부분적으로 잘려져 있었어요.

반드시 재렌더를 강요할 필요는 없습니다.

OP에 않을 수 만, 제 는 「OP」의 「OP」를 갱신하기만 하면 됩니다.width ★★★★★★★★★★★★★★★★★」height캔버스에 속성을 표시합니다(CSS에서는 할 수 없습니다).

다음과 같습니다.

import React from 'react';
import styled from 'styled-components';
import {throttle} from 'lodash';

class Canvas extends React.Component {

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

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

    resize = throttle(() => {
        this.canvas.width = this.canvas.parentNode.clientWidth;
        this.canvas.height = this.canvas.parentNode.clientHeight;
    },50)

    setRef = node => {
        this.canvas = node;
    }

    render() {
        return <canvas className={this.props.className} ref={this.setRef} />;
    }
}

export default styled(Canvas)`
   cursor: crosshair;
`

내가 방금 찾은 이 멋진 걸 공유하고 싶었어window.matchMedia

const mq = window.matchMedia('(max-width: 768px)');

  useEffect(() => {
    // initial check to toggle something on or off
    toggle();

    // returns true when window is <= 768px
    mq.addListener(toggle);

    // unmount cleanup handler
    return () => mq.removeListener(toggle);
  }, []);

  // toggle something based on matchMedia event
  const toggle = () => {
    if (mq.matches) {
      // do something here
    } else {
      // do something here
    }
  };

.matches창이 지정된 최대 너비 값보다 크거나 작을 경우 true 또는 false가 반환됩니다.이는 matchMedia가 부울이 변경되었을 때 1회만 발생하므로 리스너를 조정할 필요가 없음을 의미합니다.

내 코드는 다음을 포함하도록 쉽게 조정할 수 있습니다.useStateboolean match를 저장하기 위해 Media가 반환하고 컴포넌트, 실행 액션 등을 조건부로 렌더링하기 위해 사용합니다.

답변이 끝난 것은 알고 있습니다만, 가장 중요한 답변은, 지금은 조금 시대에 뒤떨어진 것일지도 모릅니다.

    constructor (props) {
      super(props)

      this.state = { width: '0', height: '0' }

      this.initUpdateWindowDimensions = this.updateWindowDimensions.bind(this)
      this.updateWindowDimensions = debounce(this.updateWindowDimensions.bind(this), 200)
    }

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

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

    updateWindowDimensions () {
      this.setState({ width: window.innerWidth, height: window.innerHeight })
    }

유일한 차이점은 성능 향상을 위해 크기 조정 이벤트에서 updateWindowDimensions를 디버깅(200ms마다 실행)하지만 ComponentDidMount에서 호출될 때는 디버깅하지 않는다는 것입니다.

데바운스로 인해 자주 마운트되는 상황이라면 마운트하는 것이 매우 지연된다는 것을 알게 되었습니다.

사소한 최적화일 뿐이지만 누군가에게 도움이 되길 바랍니다!

componentDidMount() {

    // Handle resize
    window.addEventListener('resize', this.handleResize);
}




handleResize = () => {
    this.renderer.setSize(this.mount.clientWidth, this.mount.clientHeight);
    this.camera.aspect = this.mount.clientWidth / this.mount.clientHeight;
    this.camera.updateProjectionMatrix();
};

크기 조정 이벤트 함수만 정의하면 됩니다.

다음으로 렌더러 사이즈(캔버스)를 갱신하고, 카메라의 새로운 애스펙트비를 할당합니다.

마운트 해제 및 리마운트하는 것은 말도 안 되는 해결책이라고 생각합니다.

아래는 필요에 따라 마운트입니다.

            <div
                className={this.state.canvasActive ? 'canvasContainer isActive' : 'canvasContainer'}
                ref={mount => {
                    this.mount = mount;
                }}
            />

@senornestor의 솔루션을 개선하기 위해forceUpdate@gkri의 솔루션을 사용하여resize구성 요소 마운트 해제 시 이벤트 수신기:

  1. 크기를 조정하기 위해 콜을 조절(또는 디바운스)하는 것을 잊지 마십시오.
  2. 꼭 하다bind(this)컨스트럭터에서
import React from 'react'
import { throttle } from 'lodash'

class Foo extends React.Component {
  constructor(props) {
    super(props)
    this.resize = throttle(this.resize.bind(this), 100)
  }

  resize = () => this.forceUpdate()

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

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

  render() {
    return (
      <div>{window.innerWidth} x {window.innerHeight}</div>
    )
  }
}

또 다른 방법은 dummy(더미) 상태를 사용하는 것입니다.forceUpdate:

import React from 'react'
import { throttle } from 'lodash'

class Foo extends React.Component {
  constructor(props) {
    super(props)
    this.state = { foo: 1 }
    this.resize = throttle(this.resize.bind(this), 100)
  }

  resize = () => this.setState({ foo: 1 })

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

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

  render() {
    return (
      <div>{window.innerWidth} x {window.innerHeight}</div>
    )
  }
}

클래스 구문과 함께 작동하기 위해 생성자의 'this'에 바인딩해야 했습니다.

class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    this.resize = this.resize.bind(this)      
  }
  componentDidMount() {
    window.addEventListener('resize', this.resize)
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.resize)
  }
}

답변해 주셔서 감사합니다.여기 '리액트' + '리컴포즈'가 있습니다.이 함수는 상위 함수로,windowHeight그리고.windowWidth컴포넌트 속성

const withDimensions = compose(
 withStateHandlers(
 ({
   windowHeight,
   windowWidth
 }) => ({
   windowHeight: window.innerHeight,
   windowWidth: window.innerWidth
 }), {
  handleResize: () => () => ({
    windowHeight: window.innerHeight,
    windowWidth: window.innerWidth
  })
 }),
 lifecycle({
   componentDidMount() {
   window.addEventListener('resize', this.props.handleResize);
 },
 componentWillUnmount() {
  window.removeEventListener('resize');
 }})
)

https://github.com/renatorib/react-sizes은 양호한 성능을 유지하면서 이를 실현하기 위한 HOC입니다.

import React from 'react'
import withSizes from 'react-sizes'

@withSizes(({ width }) => ({ isMobile: width < 480 }))
class MyComponent extends Component {
  render() {
    return <div>{this.props.isMobile ? 'Is Mobile' : 'Is Not Mobile'}</div>
  }
}

export default MyComponent

이것을 시험해 보세요:-

resize = () => this.forceUpdate()

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

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

이 때문에, CSS 또는 JSON 파일 데이터로부터 이 데이터를 사용하고, 이 데이터를 사용해 새로운 상태를 설정하는 경우({width:"some value", height:"some value" }), 또는 응답성이 높은 표시 이미지를 필요로 하는 경우, 자기 작업으로 와이드 스크린 데이터의 데이터를 사용하는 코드를 쓰는 것이 좋습니다.

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;

in index.js:

function render() {
  ReactDOM.render(<App />, document.getElementById('root'));
}

render();

window.addEventListener('resize', render);

재렌더링을 수행하면 window.innerWidth/inner 등 React가 자체적으로 검출하지 않는 변수에 따라 달라지는 모든 것이 재계산됩니다.높이, localStorage 등 앱 상태를 동일하게 유지합니다.

다른 상황에서 재렌더가 필요한 경우,는 이 렌더() 함수를 내보내고 다른 장소에서 사용할 수도 있습니다.

이것이 퍼포먼스에 미치는 영향(모든 것을 재렌더하거나 변경했을 가능성이 있기 때문에)에 대해서는 잘 모르겠습니다만, 사이징을 실시할 때는 충분히 빠른 것 같습니다.

이 주방에는 요리사가 많지만, 나는 상관하지 않고 내 모자를 던질 것이다. 중 어느 것도 「」를 사용하지 .requestAnimationFrame가장 뛰어난 성과라고 생각합니다.

으로 리액트 과 리액트 훅을 .requestAnimationFrame이것 또한 lodash와 같은 라이브러리가 없는 순수한 js를 사용하고 있습니다(번들사이즈로 인해 반드시 피하고 있습니다).

import { useState, useEffect, useCallback } from 'react';

const getSize = () => {
  return { 
    width: window.innerWidth,
    height: window.innerHeight,
  };
};
 
export function useResize() {
 
  const [size, setSize] = useState(getSize());
 
  const handleResize = useCallback(() => {
    let ticking = false;
    if (!ticking) {
      window.requestAnimationFrame(() => {
        setSize(getSize());
        ticking = false;
      });
      ticking = true;
    } 
  }, []);

  useEffect(() => {
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
 
  return size;
}

다음은 사용 중인 요약입니다.img.tsx with useResize.또는 자세한 내용은 여기 제 리포트에서 확인하실 수 있습니다.

기능을 중단하지 않고 이 작업을 수행해야 하는 이유에 대한 몇 가지 리소스:

제 테드 토크에 와주셔서 감사합니다.

언급URL : https://stackoverflow.com/questions/19014250/rerender-view-on-browser-resize-with-react

반응형