React router 4 The `Link` component only changes the URL and does not update the route

I am having problems with the response-router-dom component Link, which only changes the url and does not update the route.

It works fine with /courses -> /courses/<course-slug>
and then/courses/<course-slug> -> /lessons/<lesson-slug>

However, I am having problems linking to other lessons, for example. from/lessons/<lesson-slug> -> /lessons/<different-lesson-slug>

It seems to only update the component LessonsListand update the url, but not update the route / content or parent Lesson.

I made sure that I passed the match, location bindings to the component, if it had anything to do with update blocking - https://reacttraining.com/react-router/web/guides/dealing-with-update-blocking but it is still does not work.

I do not see where I am wrong, and it should be relatively simple.

Does this have anything to do with how I configured my routes or routes having the same?

Here I will need my dependencies and code, any point in the right direction.

"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'));

Application / 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;

Home / 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;

Lessons / 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;

Lesson / 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;

UPDATE:

Here's the updated Component with componentWillReceiveProps

Lesson / 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;
+4
source share
2 answers

<Lesson /> componentDidMount . , , . componentWillReceiveProps, , .

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

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]
            });
          });
        }
      }
0

Source: https://habr.com/ru/post/1683027/


All Articles