React Router - 带有 :id 的路径对于 HOC 包装的组件无法正常工作 [英] React Router - Path with :id is not working correctly for component wrapped by HOC

查看:34
本文介绍了React Router - 带有 :id 的路径对于 HOC 包装的组件无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用 react 和 react-router-dom 开发此应用程序 Page 组件由 HOC 包装,该 HOC 导入内容服务以访问 rest api.

我的导航位于 App 组件中.相关部分是

关于页面

联系页面

当点击这些链接时,页面不会像我预期的那样重绘.我第一次去关于页面"一切都很好.然后当我点击进入联系页面"时,没有任何变化.然后我再次点击关于页面"并显示联系页面".

在浏览器地址栏上方的所有情况下,都会显示正确的路径,如果我刷新页面,我会转到正确的页面.

这是我的导航页面:

import React, { Component } from "react";import { BrowserRouter as Router, Switch, Route, Link } from react-router-dom";从react-redux"导入{连接};从./Home"导入主页;从./Admin"导入管理员;从./Members"导入成员;从./Login"导入登录;从./Page"导入页面;从./PrivateRoute"导入PrivateRoute;导入./App.css";类 App 扩展组件 {使成为() {返回 (<路由器><div><ul><li><链接到=/">主页</链接><li><链接到=/page/123">关于页面</Link><li><链接到=/page/456">联系页面</Link><li><Link to="/members">Members</Link><li><链接到=/admin">管理员</Link>

<开关><路由路径="/login";组件={登录}/><路由路径="/page/:id";组件={页面}/><路由精确路径=/";组件={Home}/><PrivateRoute path="/members"><会员/></PrivateRoute><PrivateRoute path="/admin"><管理员/></PrivateRoute></开关></路由器>);}}const mapStateToProps = (状态) =>{返回 {isLoggedIn: state.isLoggedIn,};};导出默认连接(mapStateToProps, null)(App);

这是我的页面组件:

import React, { Component } from "react";从./WithBackend"导入WithBackend;类页面扩展组件{构造函数(道具){超级(道具);this.resource = "/pages/";this.state = { 模型:null };}使成为() {如果 (this.state.model != null) {返回 (<div className="容器"><div className="row"><div className="col-md"><h1>{this.state.model.title}</h1><h2 risklySetInnerHTML={{ __html: this.state.model.body }}/>

);} 别的 {返回 (<div><h2>页面 ID:{this.props.match.params.id}</h2>

);}}componentDidMount() {this.props.getEntity(this.resource, this.props.match.params.id).then((model) => this.setState({model }));}componentDidUpdate(nextProps) {if (nextProps.match.params.id !== this.props.match.params.id) {this.props.getEntity(this.resource, nextProps.match.params.id).then((数据) => {this.setState({模型:数据});});}}}导出默认 WithBackend(Page);

这是Withbackend HOC:

从react"导入 React;从./ContentService"导入 ContentService;const WithBackend = (WrappedComponent) =>{类 HOC 扩展了 React.Component {构造函数(){极好的();this.contentService = new ContentService();this.getEntity = this.getEntity.bind(this);this.getEntities = this.getEntities.bind(this);}getEntity(资源,ID){返回 this.contentService.getEntity(资源,ID).then((响应) => response.json()).catch((e) => {控制台日志(e);});}获取实体(资源){返回 this.contentService.getEntities(资源).then((响应) => response.json()).catch((e) => {控制台日志(e);});}使成为() {返回 (<包裹组件getEntity={this.getEntity}getEntities={this.getEntities}{...this.props}/>);}}返回 HOC;};导出默认 WithBackend;

还有内容服务:

class ContentService {baseUrl = "http://localhost:8080";getEntity(资源,ID){const 路径 = this.baseUrl + 资源 + id;const fetchPromise = fetch(path, {方法:GET",});返回 Promise.resolve(fetchPromise);}获取实体(资源){const fetchPromise = fetch(this.baseUrl + 资源,{方法:GET",});返回 Promise.resolve(fetchPromise);}}导出默认的 ContentService;

有没有人知道为什么会发生这种情况?我不确定这是否与 HOC 包装的 Page 组件有什么关系,但只是认为值得一提.

谢谢.

解决方案

Issue

componentDidUpdate 生命周期方法接收previous propsstatesnapshot 值,而不是 下一个 值.

componentDidUpdate

<块引用>

componentDidUpdate(prevProps, prevState, snapshot)

通过发送上一个"props' match param id 你是一个循环";后面.

解决方案

使用 props 中的当前 id 值.

componentDidUpdate(prevProps) {if (prevProps.match.params.id !== this.props.match.params.id) {this.props.getEntity(this.resource, this.props.match.params.id).then((数据) => {this.setState({模型:数据});});}}

Hi I have been developing this application using react and react-router-dom The Page component is wrapped by a HOC that imports a contentservice to access a rest api.

My navigation is in the App component. The relevant part is the

<Link to="/page/123">About Page</Link>

and

<Link to="/page/456">Contact Page</Link>

When these links are clicked the page doesn't redraw as i expected. First time i go to 'About Page' it's all good. Then when i click to go to 'Contact Page' nothing changes. Then i click on the 'About Page' again and the 'Contact Page' shows.

In all the cases above the browser address bar shows the right path and if i refresh the page i go to the right page.

Here is my navigation page:

import React, { Component } from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import { connect } from "react-redux";
import Home from "./Home";
import Admin from "./Admin";
import Members from "./Members";
import Login from "./Login";
import Page from "./Page";
import PrivateRoute from "./PrivateRoute";

import "./App.css";

class App extends Component {
  render() {
    return (
      <Router>
        <div>
          <ul>
            <li>
              <Link to="/">Home Page</Link>
            </li>
            <li>
              <Link to="/page/123">About Page</Link>
            </li>
            <li>
              <Link to="/page/456">Contact Page</Link>
            </li>
            <li>
              <Link to="/members">Members</Link>
            </li>
            <li>
              <Link to="/admin">Admin</Link>
            </li>
          </ul>
        </div>
        <Switch>
          <Route path="/login" component={Login} />
          <Route path="/page/:id" component={Page} />
          <Route exact path="/" component={Home} />
          <PrivateRoute path="/members">
            <Members />
          </PrivateRoute>
          <PrivateRoute path="/admin">
            <Admin />
          </PrivateRoute>
        </Switch>
      </Router>
    );
  }
}
const mapStateToProps = (state) => {
  return {
    isLoggedIn: state.isLoggedIn,
  };
};

export default connect(mapStateToProps, null)(App);

This is my page component:

import React, { Component } from "react";
import WithBackend from "./WithBackend";

class Page extends Component {
  constructor(props) {
    super(props);
    this.resource = "/pages/";
    this.state = { model: null };
  }
  render() {
    if (this.state.model != null) {
      return (
        <div className="container">
          <div className="row">
            <div className="col-md">
              <h1>{this.state.model.title}</h1>
              <h2 dangerouslySetInnerHTML={{ __html: this.state.model.body }} />
            </div>
          </div>
        </div>
      );
    } else {
      return (
        <div>
          <h2>Page id: {this.props.match.params.id}</h2>
        </div>
      );
    }
  }

  componentDidMount() {
    this.props
      .getEntity(this.resource, this.props.match.params.id)
      .then((model) => this.setState({ model }));
  }

  componentDidUpdate(nextProps) {
    if (nextProps.match.params.id !== this.props.match.params.id) {
      this.props
        .getEntity(this.resource, nextProps.match.params.id)
        .then((data) => {
          this.setState({ model: data });
        });
    }
  }
}

export default WithBackend(Page);

This is the Withbackend HOC:

import React from "react";
import ContentService from "./ContentService";

const WithBackend = (WrappedComponent) => {
  class HOC extends React.Component {
    constructor() {
      super();
      this.contentService = new ContentService();
      this.getEntity = this.getEntity.bind(this); 
      this.getEntities = this.getEntities.bind(this); 
    }  

    getEntity(resource, id) {
      return this.contentService
        .getEntity(resource, id)
        .then((response) => response.json())
        .catch((e) => {
          console.log(e);
        });
    }

    getEntities(resource) {
      return this.contentService
        .getEntities(resource)
        .then((response) => response.json())
        .catch((e) => {
          console.log(e);
        });
    }

    render() {
      return (
        <WrappedComponent
          getEntity={this.getEntity}
          getEntities={this.getEntities}
          {...this.props}
        />
      );
    }
  }
  return HOC;
};

export default WithBackend;

And the content service:

class ContentService {
  baseUrl = "http://localhost:8080";

  getEntity(resource, id) {
    const path = this.baseUrl + resource + id;
    const fetchPromise = fetch(path, {
      method: "GET",
    });

    return Promise.resolve(fetchPromise);
  }

  getEntities(resource) {
    const fetchPromise = fetch(this.baseUrl + resource, {
      method: "GET",
    });

    return Promise.resolve(fetchPromise);
  }
}

export default ContentService;

Has anyone got any ideas why this is happening? I am not sure if it has anything to do with the Page component being wrapped by HOC but just thought it is worth mentioning.

Thank you.

解决方案

Issue

The componentDidUpdate lifecycle method receives the previous props, state, and snapshot values, not the next ones.

componentDidUpdate

componentDidUpdate(prevProps, prevState, snapshot)

By sending the "previous" props' match param id you were a "cycle" behind.

Solution

Use the current id value from props.

componentDidUpdate(prevProps) {
  if (prevProps.match.params.id !== this.props.match.params.id) {
    this.props
      .getEntity(this.resource, this.props.match.params.id)
      .then((data) => {
        this.setState({ model: data });
      });
  }
}

这篇关于React Router - 带有 :id 的路径对于 HOC 包装的组件无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆