【问题标题】:How do I compose a better React list container component?如何编写更好的 React 列表容器组件?
【发布时间】:2019-04-15 17:15:38
【问题描述】:

我有一个获取电影的小应用程序。组件树不是很深。我在 App.js 中有状态,它将数据传递给 Movies.js 组件。现在,Movies.js 只是一个渲染电影 ul 列表的容器。

App.js 将数据传递给电影

<Movies
  modalData={this.state.modalData}
  toggleModal={this.openModal}
  isOpen={this.state.modalIsOpen}
  closeModal={this.closeModal}
  items={this.state.data}
  getMovieInfo={this.getMovieInfo}
  addToFavorites={this.addToFavorites}
/>

电影.js

const Movies = props => {
   const { items, getMovieInfo, addToFavorites, isOpen, toggleModal, closeModal, modalData } = props;
   const listItems = items.map((item, id) => (
     <Movie
       key={id}
       id={id}
       imdbID={item.imdbID}
       title={item.Title}
       poster={item.Poster}
       getMovieInfo={getMovieInfo}
       addToFavorites={addToFavorites}
       imdbid={item.imdbID}
       isOpen={isOpen}
       toggleModal={toggleModal}
       closeModal={closeModal}
       modalData={modalData}
     />
   ));
   return <ul id="movie-container">{listItems}</ul>;
 };

最后是 Movies.js,它只是在 Movie 组件中呈现的一个项目。我尝试使用解构来保留 Movies 组件的 items 属性,因为它需要映射然后 ...props 到 Movie。我似乎无法完成这项工作。

我的应用程序运行良好,但这是“道具钻探”,我认为上下文可能不合适,因为这不是一棵深树。高阶组件,我还不明白。我可以做些什么来改善它?

电影.js

const Movie = props => {
  const {
    id,
    imdbID,
    title,
    poster,
    getMovieInfo,
    addToFavorites,
    isOpen,
    toggleModal,
    closeModal,
    modalData,
  } = props;
  return (
    <React.Fragment>
      <li className="movie" id={id}>
        <img srcSet={poster} alt={title} imdbid={imdbID} />
        <div className="movie-title">{title}</div>
        <div className="button-container">
          <button
            type="submit"
            className="button-small"
            onClick={toggleModal}
            imdbid={imdbID}
            title={title}
            id={id}>
            {' '}
            Info!!
          </button>
          <button
            type="submit"
            className="button-small"
            onClick={addToFavorites}
            imdbid={imdbID}
            id={id}>
            {' '}
            Fav
          </button>
        </div>
      </li>
      <Modal className="modal" selector="#modal-root" isOpen={isOpen} onClick={closeModal}>
        <div className="modal-1">

【问题讨论】:

  • 代码 sn-ps 允许 ReactJS 示例。也许做一个可行(或足够接近)的例子作为 sn-p 来演示什么不起作用?
  • 该应用程序运行良好我在问如何避免道具钻孔。我通过 Movies.js 传递了这么多道具,只需要 {items},其余的都转到 Movie.js。
  • 我觉得你的评论比你的整个问题更能描述你的追求。不过,使用 Stack Overflow 的代码 sn-p 工具的工作示例会更理想。
  • 关于你的评论,为什么不把它放在一个 movieProps 道具中并传递它,让 movieProp 将它分解成必要的属性?

标签: javascript reactjs


【解决方案1】:

你可以这样做:

const Movies = ({ items, ...other}) => {

<Movie {...other} />

或者,

const { items, ...other } = props
<Movie {...other} />

您在示例中的代码:

const Movies = ({ items, ...other}) => {
   const listItems = items.map((item, id) => (
     <Movie
       key={id}
       id={id}
       {...other}
     />
   ));
   return <ul id="movie-container">{listItems}</ul>;
 };

你的更新让我害怕。您需要解构所有内容,否则它会像id={other.id} 一样持续更长的时间。如果你觉得还不错,那就去做吧:

const { items, ...other } = props
// now when you use other props like imdbid
imdbid={other.imdbid}

【讨论】:

  • 为什么我们在 中的 ...other 周围不需要大括号?
  • @KevinT。啊,对不起我的错误。已更新。
  • 现在看来,通过解构,Movie.js 没有获取数据。我进行了编辑以显示电影组件。
  • 啊,那是来自 items.map 的 id,不是吗?只需使用 id={id} 即可。
  • 请注意key={id}。这可能会在未来咬你。如果您可以使用other.imdbid 之类的内容可能会更好(只要它不为空)。
猜你喜欢
  • 1970-01-01
  • 2020-07-23
  • 2015-09-04
  • 2016-12-28
  • 1970-01-01
  • 2016-10-09
  • 2017-01-19
  • 1970-01-01
  • 2014-10-10
相关资源
最近更新 更多