如何有效地将相同的“道具”传递给每个无状态表示组件

How to efficiently pass the same "prop" to every stateless presentation component?

本文关键字:组件 表示 状态 有效地 道具      更新时间:2023-09-26

我有一个看起来简单而常见的非 DRY 代码案例 - 我希望有一种方法可以避免这种情况。

我有一个页面来呈现有关基于以下路由的对象的信息:

  <Route path="project/:projectid" component={ProjectDetails}/>

所以......"项目 ID"作为 React Router 的道具出现,每个无状态表示组件都需要生成的项目对象:

class ProjectDetails = ({project}) => {
   render() {
      return (
         <div className="project-details-page container-fluid">
             <HomeLeftBar/> 
             <div className="col-md-10">
                 <ProjectHeaderBar project={project}/>
             </div>
             <div className="project-centre-pane col-md-7">
                 <ProjectActions project={project}/>
                 <ProjectDescription project={project}/>
                 <ProjectVariations project={project}/>
             </div>
             <div className="project-right-bar col-md-3">
                 <ProjectContacts project={project}/>
                 <ProjectCosting project={project}/>
             </div>
         </div>
      )
   }
}
export default connect(
   state => ({project: state.projects[state.router.params.projectid]})
)(ProjectDetails)

应该如何清理它,这样我就不必将project传递给每个组件?


至少我注意到了几个类似的问题。 但是,虽然它们的标题相似,但它们的细节却并非如此。 他们似乎会就更具体的情况提出更高级的问题。

对我来说,通过 props 从顶部传递数据是将数据放入叶组件的最清晰方法,所以我认为你在这里所做的很好。

看起来不干净的一点是,您将整个project对象传递给每个组件,但乍一看,似乎每个组件都只负责呈现该project对象的一部分。

仅传递每个组件所需的project分支将使数据和视图之间的关系更加清晰。

<ProjectContacts project={project.contracts}/> <ProjectCosting project={project.costing}/>

反过来,我认为这将使整个组件感觉更干净:

class ProjectDetails = ({project: { costings, description, variations, title, actions, contacts} }) => {
   render() {
      return (
         <div className="project-details-page container-fluid">
             <HomeLeftBar/> 
             <div className="col-md-10">
                 <ProjectHeaderBar title={title}/>
             </div>
             <div className="project-centre-pane col-md-7">
                 <ProjectActions actions={actions}/>
                 <ProjectDescription description={description}/>
                 <ProjectVariations variations={variations}/>
             </div>
             <div className="project-right-bar col-md-3">
                 <ProjectContacts contacts={contacts}/>
                 <ProjectCosting costings={costings}/>
             </div>
         </div>
      )
   }
}

我假设你正在使用反应路由器。你可以做这样的事情:

        <Router history={history}>
            <Route path="project/:projectId">
                <Route path="participants" component={Participants} />
                <Route path="progress" component={Progress}/>
            </Route>
        </Router>

<Route path="project/:projectId">的所有孩子都可以使用this.props.params.projectId。例如,指向参与者组件的 url 是"project/:projectId/participants"的,因此projectId在呈现参与者时是一个参数。

此外,如果项目详细信息应在所有页面上以相同的方式呈现,则可以在路由上将组件添加到"project/:p rojectId",该组件负责渲染项目详细信息。(该组件将接收参与者或进度作为this.props.children,您必须在新组件中呈现。