防止使用shouldComponentUpdate()重新安装昂贵的(类)组件(图像列表,路由器内部)

时间:2019-08-08 05:55:54

标签: reactjs react-router state react-hooks

我正在渲染非常大的图像列表,当单独单击它们时,这些图像将添加到“查看器” div中。问题在于,即使未对列表内容进行任何更改,每次我向查看器添加图像时,原始列表也会重新呈现。

我尝试过在每个级别使用shouldComponentUpdate()以及使用React.memo。两者似乎都没有任何作用。我还研究了是否应该花费时间使组件发挥功能并研究钩子(useContext()看起来很诱人),但是我在React还是太新了,无法知道这是否会浪费更多时间。 (请随意权衡这是否浪费时间。)

我不知道问题出在哪里,所以我不确定片段是否会带来很多好处。相反,我将问题简化了一下,并在此处发布了沙盒版本

https://codesandbox.io/s/async-darkness-l920b

此刻,我的shouldComponentUpdate比较对于每个班级都非常简单;像这样:

if (nextProps.photoData === this.props.photoData) {
  return false;
} else {
  return true;
}

如果打开codesandbox控制台,您会看到我正在登录Year.js > <ImageList /> is rendering来标记有问题的列表的每个后续呈现。

任何帮助,甚至是朝着正确方向前进的帮助,都将不胜感激。我一直在阅读博客文章,现在情况不错,似乎没有任何帮助。

1 个答案:

答案 0 :(得分:1)

这是因为PhotoView中的App.js是在render方法中定义的,因此当状态更新导致渲染时,PhotoView会重新定义。每次都是App组件的新组件。

请在渲染功能之外定义组件:

import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import Year from "./Year";
import Viewer from "./Viewer";
import dataObj from "./dataObj.json";
import "./App.css";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.PhotoView = this.PhotoView.bind(this)
    this.state = {
      current: {
        year: 2019,
        url: ""
      },
      viewerData: [],
      photoData: null
    };
  }

  componentDidMount() {
    this.setState({
      photoData: dataObj
    });
  }

  addToViewer = moment =>
    this.setState(state => {
      const viewerData = state.viewerData.concat(moment.props.data);
      return {
        viewerData,
        value: ""
      };
    });
  About() {
      return (
        <div>
          <h1>About</h1>
        </div>
      );
    };
  PhotoView(url) {
      return (
        <div className="PhotoView">
          <Year
            setCurrent={this.setCurrent}
            photoData={this.state.photoData}
            addToViewer={this.addToViewer}
          />
          <Viewer
            viewerData={this.state.viewerData}
            setCurrent={this.setCurrent}
          />
        </div>
      );
    }
  render() {
    return (
      <div className="App">
        <Router>
          <nav>
            <Link to="/about">About</Link>
            <Link to="/">Photo View</Link>
          </nav>
          <Switch>
            <Route path="/about" exact component={this.About} />
            <Route path="/" component={this.PhotoView} />
          </Switch>
        </Router>
      </div>
    );
  }
}

export default App;

或将它们移至单个文件。