React router 4`Link`组件仅更改URL而不更新路由

时间:2017-08-04 15:40:09

标签: reactjs react-router react-router-v4 react-router-dom

我在react-router-dom Link组件遇到问题时只更改了URL而没有更新路由。

/courses -> /courses/<course-slug>起,它可以正常链接 然后/courses/<course-slug> -> /lessons/<lesson-slug>

然而,我在链接到其他课程时遇到问题,例如来自/lessons/<lesson-slug> -> /lessons/<different-lesson-slug>

似乎它只会更新LessonsList组件并更新网址,但不会更新路线/内容或父Lesson

我已确保将匹配,位置支持传递给组件,因为它与更新阻止有关 - https://reacttraining.com/react-router/web/guides/dealing-with-update-blocking但它似乎仍无法正常工作。

我无法看到我出错的地方,而且应该相对简单。

是否与我如何设置路线或路线相同有什么关系?

这里是我的依赖关系和代码,正确方向的任何一点都会受到赞赏。

"dependencies": {
    "axios": "^0.16.2",
    "prop-types": "^15.5.10",
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-router-dom": "^4.1.2"
 }

index.js

    import css from '../css/index.scss';
    import React from 'react';
    import ReactDOM from 'react-dom';
    import { BrowserRouter as Router } from 'react-router-dom';
    import App from './components/App';

    ReactDOM.render(
      <Router>
        <App />
      </Router>
    , document.getElementById('app'));

应用/ index.js

import React, { Component } from 'react';
import Header from '../Header';
import Main from '../Main';
import Footer from '../Footer';

class App extends Component {
  render() {
    return(
      <div>
        <Header />
        <Main />
        <Footer />
      </div>
    );
  }
}

export default App;

主/ index.js

import React, { Component } from 'react';
import { Route, Link, Switch } from 'react-router-dom';
import Home from '../Home';
import Courses from '../Courses';
import Course from '../Course';
import Lessons from '../Lessons';
import Lesson from '../Lesson';

class Main extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return(
      <div className="main">
        <Switch>
          <Route exact path="/" component={Home}/>
          <Route path="/courses/:course" component={Course}/>
          <Route exact path="/courses" component={Courses}/>
          <Route path="/lessons/:lesson" component={Lesson}/>
          <Route exact path="/lessons" component={Lessons}/>
          <Route render={ () => (
            <div>Not Found 404</div>
          )}/>
        </Switch>
      </div>
    );
  }
}

export default Main;

吸取/ index.js

import React, { Component } from 'react';
import api from '../../utils/api';
import LessonsList from '../LessonsList';
import { Link } from 'react-router-dom';

class Lessons extends Component {
  constructor(props) {
    super(props);

    this.state = {
      lessons: null
    };
  }

  componentDidMount() {
    api.getAllLessons()
      .then((lessons) => {
        this.setState({
          lessons: lessons
        });
      });
  }

  render() {
    return(
      <div className="lessons">
        {!this.state.lessons ?
          <div>Loading...</div>
          :
          <div>
            <LessonsList 
              lessons={this.state.lessons}
              {...this.props}
            />
          </div>
        }
      </div>
    );
  }
}

export default Lessons;

课程/ index.js

import React, { Component } from 'react';
import api from '../../utils/api';
import LessonsList from '../LessonsList';
import { Link } from 'react-router-dom';

class Lesson extends Component {
  constructor(props) {
    super(props);

    this.state = {
      lesson: null
    }
  }

  componentDidMount() {
    api.getLesson(this.props.match.params.lesson)
      .then((lesson) => {
        this.setState({
          lesson: lesson[0]
        });
      });
  }

  render() {
    return(
      <div className="lesson">
        {!this.state.lesson ?
          <div>Loading...</div>
          :
          <div>
            <h3>Course title: {this.state.lesson.course.title}</h3>
            <h1>Lesson: {this.state.lesson.title}</h1>
            <h2>Other lessons from this course</h2>
            <LessonsList
              lessons={this.state.lesson.lessons}
              {...this.props}
            />
          </div>
        }
      </div>
    );
  }
}

export default Lesson;

LessonsList / index.js

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';

function LessonsList(props) {
  return(
    <ul>
      {props.lessons.map((lesson) => {
        return(
          <li key={lesson.id}>         
            <Link to={`/lessons/${lesson.slug}`}>{lesson.title}</Link>
          </li>
        );
      })}
    </ul>
  );
}

LessonsList.propTypes = {
  lessons: PropTypes.array.isRequired
}

export default LessonsList;

更新

此处使用componentWillReceiveProps

更新了组件

课程/ index.js

import React, { Component } from 'react';
import api from '../../utils/api';
import LessonsList from '../LessonsList';
import { Link } from 'react-router-dom';

class Lesson extends Component {
  constructor(props) {
    super(props);

    this.state = {
      lesson: null
    }
  }

  componentDidMount() {
    api.getLesson(this.props.match.params.lesson)
      .then((lesson) => {
        this.setState({
          lesson: lesson[0]
        });
      });
  }

  componentWillReceiveProps(nextProps) {
    if(this.props.match.params.lesson !== nextProps.match.params.lesson) {
      api.getLesson(nextProps.match.params.lesson)
        .then((lesson) => {
            this.setState({
            lesson: lesson[0]
          });
        });
    }
  }

  render() {
    return(
      <div className="lesson">
        {!this.state.lesson ?
          <div>Loading...</div>
          :
          <div>
            <h3>Course title: {this.state.lesson.course.title}</h3>
            <h1>Lesson: {this.state.lesson.title}</h1>
            <h2>Other lessons from this course</h2>
            <LessonsList
              lessons={this.state.lesson.lessons}
              {...this.props}
            />
          </div>
        }
      </div>
    );
  }
}

export default Lesson;

2 个答案:

答案 0 :(得分:2)

您的<Lesson />组件仅在componentDidMount生命周期挂钩期间设置课程。如果您正在上课并更改了slug,则不会导致组件重新装入。您可以使用componentWillReceiveProps生命周期钩子来完成您所追求的目标。

componentWillReceiveProps(nextProps) {
    api.getLesson(nextProps.match.params.lesson)
        .then((lesson) => {
            this.setState({
            lesson: lesson[0]
        });
    });
}

答案 1 :(得分:0)

componentDidMount事件的这个问题。更改课程时不会被解雇。因此,您应该使用componentDidUpdate来更改课程。

  componentDidUpdate() {
    if (this.props.match.params.lesson !== this.state.lesson.slug)
     api.getLesson(this.props.match.params.lesson)
          .then((lesson) => {
            this.setState({
              lesson: lesson[0]
            });
          });
        }
      }