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

Posted

技术标签:

【中文标题】如何让 QueryRenderer 传播父道具更改?【英文标题】:How to get the QueryRenderer to propagate parent prop changes? 【发布时间】:2018-07-02 13:02:03 【问题描述】:

使用 Relay Modern v.1.4.1,考虑以下List 组件。

它需要两个 props foobar 并使用这些 props 和 GraphQL 查询的结果呈现一个 Table 组件:

class List extends React.Component 

  constructor(props) 
    super(props);
    // I accept this.props.foo and this.props.bar
    this.renderQuery = this.renderQuery.bind(this);
  

  render() 
    return <QueryRenderer
      environment=this.props.relayEnvironment
      query=SomeQuery
      variables=
        count: 20,
      
      render=this.renderQuery
    />;
  

  renderQuery(readyState) 
    console.log("List component props:");
    console.log(this.props);
    return <Table 
      foo=this.props.foo bar=this.props.bar 
      data=readyState.data
    />
  


现在,对于 Table 组件的初始渲染,foobar 设置正确,但是如果 foobar 之后发生更改,则新值不会传播到 Table 组件,因为QueryRenderer.

由于QueryRenderer 仅在variables 更改SomeQuery 时才会重新渲染,因此renderQuery 方法没有被触发,因为QueryRenderer 认为不需要它,所以Table 组件保留使用旧的道具值。

由于将 props 传递给孩子是一项非常常见的任务,QueryRenderer 忽略父母的 prop 更改这一事实造成了很大的问题。我一直想知道解决方案可能是什么,并提出了一些选择:

    使用Context 绕过此行为。但是,除非您有充分的理由,否则通常不鼓励使用 Context + 绕过该问题感觉像是一种肮脏的黑客行为。 强制QueryRenderer 使用与以前相同的readyState 重新渲染。这也许可以使用refs 来实现,但您需要自己检查何时重新渲染。 不知何故让QueryRenderer 关心我的道具。这显然是正确的方法,但我在文档中没有找到任何允许这样做的东西,所以我需要做一些事情,比如从 QueryRenderer 或其子类创建一个高阶组件来实现这种行为。李>

理想情况下,我希望有一种本地方式让 QueryRenderer 查看道具更改,例如

<QueryRenderer
  environment=this.props.relayEnvironment
  query=SomeQuery
  variables=
    count: 20,
  
  render=this.renderQuery
  propagateProps=this.props
/>

<QueryRenderer
  environment=this.props.relayEnvironment
  query=SomeQuery
  variables=
    count: 20,
  
  render=this.renderQuery
  ...this.props
/>

有什么想法吗?

【问题讨论】:

【参考方案1】:

删除你的 Class 组件并将上面的代码更改为:

const List = (parentProps) => (
  <QueryRenderer
    environment=parentProps.relayEnvironment
    query=SomeQuery
    variables=
      count: 20,
    
    render=( props ) => (
      <Table 
        foo=this.parentProps.foo bar=this.parentProps.bar 
        data=props.data
      />
    )
  />
)

QueryRenderer 本身已经是一个 React 组件,您通常不必将它包装在类组件渲染中。

List 现在是一个纯函数组件,当它收到新的 props (parentProps) 时会重新渲染,因此 Table 也会重新渲染

【讨论】:

以上是关于如何让 QueryRenderer 传播父道具更改?的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL / Relay - 是不是需要在主 QueryRenderer 中查询所有表?

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

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

ReactJS setState 更改不会从父组件传播到子组件[重复]

如何在 Relay Modern 的父组件中最好地访问来自 QueryRenderer 的数据?

使用传播属性时如何在子组件中获取道具