【问题标题】:Should I use props or states in order to pass data?我应该使用道具或状态来传递数据吗?
【发布时间】:2017-04-03 18:39:41
【问题描述】:

我正在从 API 获取一组项目(call'em 电影)。每部电影都有几个细节(标题、导演、演员、概要等)

这是我的结构图:

这是 MoviesList 组件:

 constructor(props) {
    super(props);

    this.state = {
      movies: []
    };
  }

  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)
      })
  }

  render() {
    return (
      <div className="movies">
        <Movie movies={this.state.movies}></Movie>
      </div>
    );
  }

这是电影:

render() {

    const movielist = this.props.movies.map((movie) =>
        <li>{movie.title}</li>
    );

    return (
      <ul className="movie">
        { movielist }
      </ul>
    );

}

我的问题:

  1. 我应该使用 state 还是 props 将数据从 Movielist 传递到 Movie
  2. 由于没有“for”模板,我该如何制作,所以我不会在 Movie 内创建列表,而是在 Movielist 内循环整个 Movie 组件?

比如我想在MovieList里面实现如下:

  render() {
    return (
      <div className="movies">
        <Movie for movie in movies></Movie>
      </div>
    );
  }

【问题讨论】:

  • 为什么不让movielist在其渲染过程中进行映射,而movie只显示1部电影?发送到电影的详细信息应该/应该通过道具,电影列表可以有状态,但您也可以添加一些 MovieStore 并让它定义电影列表的状态
  • 这正是我想要做的——(还不熟悉商店,一步一步来)——你介意用替代实现添加答案吗?
  • 如果您以这种方式使用您的组件,为什么不将它们命名为smartdumb 组件?所以你的MoviesList实际上是Container应该获取数据并通过props传递给组件)而movieComponent应该只显示接收到的数据我>)。在这种情况下,将movie 重命名为DumbMovieList 可能更好:) 所以总的来说,在你的例子中这是一个好方法。为什么需要for in?对我来说const movielist = this.props.movies.map 是个好方法!还是有什么问题?
  • @OlegPro for in 部分是伪代码,用于显示我想要实现的目标。 (旁注:我确实发现映射部分很难阅读,这对我来说并不自然。)

标签: javascript reactjs


【解决方案1】:

MovieList 中的render()

  render() {
    return (
      <div className="movies">
        {
          this.state.movies
          ? <ul>
              {this.state.movies.map((movie, index) => <Movie title={movie.title} key={index}/>)}
            </ul>
          : null
        }
      </div>
    );
  }

render()Movie

  render() {
    return (
      <li className="movie">{this.props.title}</li>
    );
  }

【讨论】:

  • 如何传递整个电影项目而不仅仅是标题?
  • @GeorgeKatsanos 只需使用&lt;Movie {...movie} /&gt; ;)
  • 正如@Icepickle 所说,您可以隐式执行:&lt;Movie {...movie} /&gt; 或显式:&lt;Movie title={movie.title} /&gt; 或作为对象movieData&lt;Movie movieData={movie} /&gt;。现在在Movie 中,您可以访问this.props.movieData.title
  • 有什么方法可以让 MovieList 渲染代码更具可读性吗?还有更多“这是一个循环”的直接方式还是写这个? (我想念模板..)
  • @free-soul 最后一件事:我得到了warning.js:36 Warning: Each child in an array or iterator should have a unique "key" prop
【解决方案2】:

i props/state - 我认为你所做的很好;将外部组件 (MoviesList) 的状态作为道具传递给其子组件(您不会使用 api 调用的结果设置外部组件自己的属性)。

ii 您可以在外部组件中映射电影,例如:

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

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

【讨论】:

  • 什么是“renderMovie”?
  • 抱歉,George,只是一个用于实现电影渲染的存根;我会更新答案。
  • 马克,想象一下这部电影不仅有一个名字,还有我想显示的许多其他属性——因此我不想在 MoviesList 中做所有这些,而只是将所有内容传递给 Movie让它处理渲染..
  • 然后 renderMovie 方法可以渲染 Movie 组件,但是在您的原始版本中,Movie 接受了一个电影列表作为道具,而 Movie 组件现在只需要一个电影实例并渲染它? (我已经更新了答案。)
  • 这与您的组件的复数形式相匹配(即,电影应该只关注渲染电影的一个实例。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
  • 2018-09-02
相关资源
最近更新 更多