如何将自定义道具传递给 QueryRenderer 渲染函数?

Posted

技术标签:

【中文标题】如何将自定义道具传递给 QueryRenderer 渲染函数?【英文标题】:How to pass custom props into QueryRenderer render function? 【发布时间】:2018-01-28 07:07:17 【问题描述】:

给定以下 QueryRenderer 组件:

class ProjectQueryRenderer extends Component 
  constructor(props) 
    super(props);
    this.renderProjectList = this.renderProjectList.bind(this);
  

  renderProjectList( error, props ) 
    if (props) 
      return (
        <ProjectList
          connection=props.viewer.allProjects
          onSelectProject=this.props.onSelectProject
          selectedProject=this.props.selectedProject
        />
      );
    
  

  render() 
    return (
      <QueryRenderer
        environment=environment
        query=ProjectsQuery
        render=this.renderProjectList
      />
    );
  


ProjectQueryRenderer.propTypes = 
  onSelectProject: Proptypes.func.isRequired,
  selectedProject: Proptypes.string.isRequired,
;

我遇到的问题是,当我自己的 selectedProject 属性更改值时,renderProjectList 不会再次执行。 render 方法显然确实被触发了,但是由于 QueryRenderer 的任何属性都没有改变,renderProjectList 也没有被调用。

处理这个问题的最佳方法是什么?

【问题讨论】:

【参考方案1】:

我找到了一个解决方案,每次我注入的一个道具发生变化时,它都会成功地重新呈现我的列表组件(不执行 api 请求)。我必须在 render 函数中定义我的组件,以便我可以访问新的 prop 值。

作为功能组件的结果如下:

const ProjectQueryRenderer = ( onSelectProject, selectedProject ) => 
  const comp = ( error, props ) => 
    if (props) 
      return (
        <ProjectList
          connection=props.viewer.allProjects
          onSelectProject=onSelectProject
          selectedProject=selectedProject
        />
      );
    
  ;
  return (
    <QueryRenderer
      environment=environment
      query=ProjectsQuery
      render=comp
    />
  );
;

【讨论】:

这种方法的缺点是每次ProjectQueryRenderer 需要渲染时,您都会为comp 函数创建一个新定义。【参考方案2】:

除了将渲染函数传递给QueryRenderer,您还可以将整个 ProjectList 组件作为属性以及该组件需要从父组件渲染的任何道具传递。他们额外的道具在QueryRenderer 中显示为other。见下文:

class ProjectQueryRenderer extends Component 
  render() 
    return (
      <QueryRenderer
        environment=environment
        query=ProjectsQuery
        component=ProjectList
        onSelectProject=this.props.onSelectedProject
        selectProject=this.props.selectedProject
      />
    );
  


ProjectQueryRenderer.propTypes = 
  onSelectProject: Proptypes.func.isRequired,
  selectedProject: Proptypes.string.isRequired,
;

现在是 QueryRenderer

class QueryRenderer extends Component 

  render() 
    const environment, query, component, ...other = this.props 

    // parameters to component that QueryRenderer computes
    // based on environment, query, etc...
    // plus also pass in all the extra props that are coming from
    // ProjectQueryRenderer (like onSelectProject)
    const computedProp = //something

    return (
     <div>
       <component computedProp=computedProp ...other />
     </div>
   )
  

这样,ProjectQueryRenderer 和 QueryRenderer 都可以将 props 传递给任意组件到 QueryRenderer 中,您也可以在其他类型的组件中重用 QueryRenderer。

【讨论】:

不确定我是否理解正确。上面的示例给出了Uncaught TypeError: this.props.render is not a function 错误。 我将 render 属性名称更改为 component,但您可以自行决定是否为它找到合适的名称。也许我的解决方案并不完全是您正在寻找的。我又在看它,我正在工作。 ProjectList 是否依赖于从 ProjectQueryRendererQueryRenderer 过去的属性?如果是这样,这个问题还有另一种解决方案。

以上是关于如何将自定义道具传递给 QueryRenderer 渲染函数?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Material UI 和 TypeScript 将自定义道具传递给样式化组件?

将自定义道具传递给 TypeScript 中的 Redux 表单字段

中继 QueryRenderer fragmentContainer 传递的道具与服务器响应不同,因为 id 冲突

如何将自定义道具从 App 传递到单元格以进行 react-table v7?

如何让 QueryRenderer 传播父道具更改?

如何使用 Relay QueryRenderer 道具更新状态