使用 React 在浏览器上重新渲染视图调整大小

新手上路,请多包涵

调整浏览器窗口大小时,如何让 React 重新渲染视图?

背景

我有一些想要在页面上单独布局的块,但是我也希望它们在浏览器窗口更改时更新。最终的结果将类似于 Ben Holland 的 Pinterest 布局,但使用 React 而不仅仅是 jQuery 编写。我还有一段路要走。

代码

这是我的应用程序:

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 组件(相当于上面 Pinterest 示例中的 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>
    );
  }
});

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
});

有没有更“反应”的方式来做到这一点?

原文由 digibake 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.7k
2 个回答

使用反应钩子:

您可以定义一个自定义 Hook 来监听窗口 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);
 }
 }

原文由 Sophie Alpert 发布,翻译遵循 CC BY-SA 4.0 许可协议

@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);
    }
});

原文由 Andre Pena 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题