2017-08-04 1 views
4

Ich habe Probleme mit react-router-dom Link Komponente nur die URL ändern und nicht die Route zu aktualisieren.React Router 4 `Link` Komponente nur die URL ändern und nicht die Route aktualisieren

Es funktioniert gut Verknüpfung von /courses -> /courses/<course-slug>
und dann /courses/<course-slug> -> /lessons/<lesson-slug>

aber es die Ich habe Probleme zum Beispiel mit anderen Lektionen Verknüpfung von /lessons/<lesson-slug> -> /lessons/<different-lesson-slug>

Es scheint, als ob es nur aktualisiert die LessonsList Komponente und aktualisiert die URL, aber aktualisiert nicht die Route/Inhalt oder Eltern Lesson.

Ich habe dafür gesorgt, dass Match, Location Requisiten auf die Komponente übergeben werden, wenn es etwas mit Update-Blockierung zu tun hatte - https://reacttraining.com/react-router/web/guides/dealing-with-update-blocking, aber es scheint immer noch nicht zu funktionieren.

Ich kann nicht sehen, wo ich falsch liege, und es sollte relativ einfach sein.

Hat es irgendetwas damit zu tun, wie ich meine Routen eingerichtet habe oder die Routen die gleichen haben?

Hier ist meine Abhängigkeiten und Code, jeder Punkt in die richtige Richtung wäre willkommen.

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

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; 

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

Lektionen/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:

Hier ist die aktualisierte Komponente mit 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; 

Antwort

1

Ihre <Lesson /> Komponente setzt nur die Lektion während des componentDidMount Lifecycle-Haken. Wenn Sie in einer Lektion sind und den Block ändern, wird die Komponente nicht neu mounted. Sie können den Lebenszyklus-Hook componentWillReceiveProps verwenden, um das zu erreichen, wonach Sie suchen.

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

Dies war der Punkt in die richtige Richtung, die ich brauchte! Vielen Dank. Obwohl ich die aktualisierten Requisiten übergeben musste, um den neuen Slug zu bekommen. – user3178098

0

Dieses Problem mit ComponentDidMount-Ereignis. Es wird nicht ausgelöst, wenn Sie die Lektion wechseln. Daher sollten Sie componentDidUpdate verwenden, um eine Lektion zu ändern.

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

Warum sollten Sie nach dem Update warten, um setState zu verwenden? –

+0

Wir können auch componentWillReceiveProps verwenden, es ist nicht kritisch, Daten werden nach dem Update trotzdem in den Status übergeben. –

+0

Die Verwendung des componentDidUpdate-Hooks führt zu einem fremden Rendern. Es ist nicht das schlimmste Ding auf der Welt, es ist einfach nicht nötig. –

Verwandte Themen