【问题标题】:Prevent remounting of layout component if react router params stay the same如果反应路由器参数保持不变,则防止重新安装布局组件
【发布时间】:2019-02-18 10:55:30
【问题描述】:

我有一个布局组件,它呈现一个相当大的图像。此布局组件在其他两个组件 Map 和 Explore 之间共享。当路线发生变化时,它会渲染 Map 或 Explore 组件,并将 layout 组件包裹在其周围。

用户通过主页访问 Map 或 Explore。因此,该页面的链接可能是“.../map/123”或“.../explore/456”。一旦用户在地图或探索组件中,在地图和探索之间切换时,url 参数始终保持不变。所以'.../map/123'或'.../explore/123'

在每次路线更改时,布局组件和地图/探索组件都会重新渲染。问题是布局组件上的大图像随后被重新获取。

我应该如何构建应用程序,以便我可以从 Map and Explore 切换而无需重新获取大图像?

我的代码在this sandbox...

//index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, NavLink } from "react-router-dom";

import "./styles.css";

import Map from "./Map";
import Explore from "./Explore";

const Links = props => {
  return (
    <nav>
      <NavLink exact to="/">
        Home
      </NavLink>
      <NavLink style={{ paddingLeft: "5px" }} to="/map/1">
        Map
      </NavLink>
      <NavLink style={{ paddingLeft: "5px" }} to="/explore/1">
        Explore
      </NavLink>
    </nav>
  );
};

function App() {
  return (
    <Router>
      <div>
        <Links />
        <Route exact path="/" render={() => <h1>Home</h1>} />
        <Route path="/map/:id" render={({ match }) => <Map match={match} />} />
        <Route
          path="/explore/:id"
          render={({ match }) => <Explore match={match} />}
        />
      </div>
    </Router>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

//layout MapExploreContainer.js
import React, { Component } from "react";

class MapExploreContainer extends Component {
  state = { imgUrl: null };

  componentDidMount() {
    this.timeout = setTimeout(() => {
      this.setState({
        imgUrl:
          "https://images.unsplash.com/photo-1550396011-0d98206d5b92?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjU1Nzk4fQ"
      });
    }, 2000);
  }

  componentWillUnmount() {
    clearInterval(this.timeout);
  }

  render() {
    console.log("hi: ", this.props.match);
    return (
      <div style={{ border: "1px solid black" }}>
        <img src={this.state.imgUrl} />
        {this.props.children}
      </div>
    );
  }
}

export default MapExploreContainer;

//Map.js
import React, { Component } from "react";
import MapExploreContainter from "./MapExploreContainer";

class Map extends Component {
  render() {
    return (
      <MapExploreContainter match={this.props.match}>
        <div>Map</div>
      </MapExploreContainter>
    );
  }
}

export default Map;

//Explore.js
import React, { Component } from "react";
import MapExploreContainter from "./MapExploreContainer";

class Explore extends Component {
  render() {
    return (
      <MapExploreContainter match={this.props.match}>
        <div>Explore</div>
      </MapExploreContainter>
    );
  }
}

export default Explore;

【问题讨论】:

    标签: reactjs optimization react-router


    【解决方案1】:

    我认为这里的问题是ExploreMap 都有自己的MapExploreContainer 实例,当这些组件中的每一个都被卸载时,它也会被卸载。

    您可以尝试以下方法:

    MapExplore 中删除对MapExploreContainter 的所有引用

    将您的路线更改为:

    function App() {
      return (
        <Router>
          <div>
            <Links />
            <Route exact path="/" render={() => <h1>Home</h1>} />
            <Route path="/(map|explore)/:id" component={MapExploreContainter} />
            <Route path="/map/:id" render={({ match }) => <Map match={match} />} />
            <Route
              path="/explore/:id"
              render={({ match }) => <Explore match={match} />}
            />
          </div>
        </Router>
      );
    }
    

    这样,无论您在map/123explore/123,呈现的MapExploreContainer 始终是同一个实例。

    更新沙盒:https://codesandbox.io/s/14xj47667j

    【讨论】:

    • 对,根据url,要么渲染Map,要么渲染Explore组件……?
    • 如果你输入例如/map/123 路由器将匹配 /map/:id 但也匹配 (map|explore)/:id 因为路由器使用 path-to-regexp 您可以使用正则表达式来匹配路由。当您导航到 /explore/:123 时,它将卸载 map 并装载 explore 但不是容器,因为它仍然匹配路线。
    猜你喜欢
    • 2017-09-11
    • 1970-01-01
    • 2020-04-18
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-23
    • 2021-09-28
    相关资源
    最近更新 更多