使用路由器路径显示详细的项目视图

时间:2016-11-20 23:25:53

标签: reactjs react-router

diagram components

我的Movielist组件看起来有点像:

componentDidMount() {
        fetch('http://localhost:3335/movies')
        .then(function(response) {
            return response.json()
        }).then((movies) => {
            this.setState({ movies });
        }).catch(function(ex) {
            console.log('parsing failed', ex)
        })
    }

    renderMovie(movie) {
        return (
          <Movie movie={movie} key={movie.id}></Movie>
        );
    }

    render() {
        return (
            <div className="movies columns is-multiline">
                { this.state.movies.map(this.renderMovie) }
            </div>
        );
    }

我的Movie组件有一个<Link>

shouldComponentUpdate() {
    debugger;
    if (this.props.params) {
        let activeMovie = find(this.state.movies, {'id': this.props.params.id});
        debugger;
        this.setState({ movies: activeMovie });
    }
}

render() {
        return (
    <Link to={`/movies/${this.props.movie.id}`}/>

... 在我的index.js中,我设置了以下路线:

ReactDOM.render((
        <Router history={hashHistory}>
            <Route path="/" component={App}>
                <Route path="/movies/(:id)" component={Movie}/>
            </Route>
        </Router>
    ),
    document.getElementById('root')
);

我希望每次点击<Link>,获取param.id并仅显示该电影(有类似lodash的内容):

let activeMovie = find(this.state.movies, {'id': this.props.params.id});

不幸的是this.props.params未定义。

基本上只有一个Movie组件的实例加载到内存中。 (理想情况下,不会丢失以前的电影,因此每次进入列表视图时都会避免接听新电话)

这就像一个Todo应用程序,但有电影而不是Todos ..

1 个答案:

答案 0 :(得分:0)

  1. 您的路线参数未传递到您的电影组件,而您正尝试在电影组件中访问它。 params只传递给Movielist Component。
  2. MovieList

    renderMovie(movie) { 
       return ( 
        <Movie
        params={this.props.params}
        movie={movie}
        key={movie.id}
        ></Movie>   
       ); 
    }
    
    1. 您应该删除Movie Component中的函数shouldComponentUpdate。因为当网址改变了。 params将传递给您的MovieList组件,componentWillReceiveProps将接收参数。因此,您可以直接更新MovieList,而无需将参数传递给Movie Component。
    2. MovieList

      componentWillReceiveProps(nextProps) {
        let activeMovie = find(this.state.movies, {'id': nextProps.params.id});
        this.setState({ movies: activeMovie, }
      }
      

      但这会失去你的电影状态。所以我认为您需要添加如下所示的嵌套路线,并为电影详情提供单独的页面。

      ReactDOM.render((
              <Router history={hashHistory}>
                  <Route path="/" component={App}>
                      <Route path="/movies" component={MovieList}>
                        <Route path="/:id" component={Movie}>
                      </Route>
                  </Route>
              </Router>
          ),
          document.getElementById('root')
      );
      
      const {
        Router,
        Route,
        IndexRoute,
        Redirect,
        Link,
        IndexLink,
        browserHistory
      } = ReactRouter;
      
      const {
        Component,
            } = React;
      
      class App extends Component {
        constructor(props) {
          super(props);
        }
        render() {
          return (
            <div className="container">
             { React.Children.toArray(this.props.children) }
            </div>
          )
        }
      }
      
      class MovieList extends Component {
        constructor(props) {
          super(props);
          this.state = {
            movies: []
          };
          this.renderMovies = this.renderMovies.bind(this);
        }
        componentDidMount() {
          this.setState({
            movies: [
              { id: '1', name: 'Fantastic Beasts And Where To Find Them'},
              { id: '2', name: 'Ouija: Origin Of Evil'},
              { id: '3', name: 'Marvel\'s Doctor Strange'}]
          })
        }
        renderMovies() {
          return this.state.movies.map(movie => <li key={movie.id}><Link to={`/js/${movie.id}`}>{movie.name}</Link></li>)
        }
        render() {
          return (
            <div>
              <h1>Movies</h1>
              <ul>
                {this.renderMovies()}
              </ul>
            </div>
          )
        }
      }
      
      class Movie extends Component {
        constructor(props) {
          super(props);
        }
        render() {
          return (
           <div>{this.props.params.movieId}</div>
          );
        }
      }
      
      ReactDOM.render((
        <Router history={browserHistory}>
          <Route path="/js" component={App}>
            <IndexRoute component={MovieList} />
            <Route path="/js/:movieId" component={Movie} />
          </Route>
        </Router>
      ), document.getElementById('root'))
      

      我创建了一个有效的jsbin示例。希望它有所帮助。