React router 4`Link`组件只更改url而不更新路由

use*_*098 5 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组件并更新URL,但不更新路由/内容或父级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"
 }
Run Code Online (Sandbox Code Playgroud)

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'));
Run Code Online (Sandbox Code Playgroud)

应用/ 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;
Run Code Online (Sandbox Code Playgroud)

主/ 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;
Run Code Online (Sandbox Code Playgroud)

教训/ 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;
Run Code Online (Sandbox Code Playgroud)

课程/ 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;
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

更新:

这是更新的组件 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;
Run Code Online (Sandbox Code Playgroud)

Kyl*_*son 2

您的<Lesson />组件仅在生命周期挂钩期间设置课程componentDidMount。如果您在上课时更换了 slug,则不会导致组件重新安装。您可以使用componentWillReceiveProps生命周期挂钩来完成您想要的事情。

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