【问题标题】:How to get the QueryRenderer to propagate parent prop changes?如何让 QueryRenderer 传播父道具更改?
【发布时间】: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 更改这一事实造成了很大的问题。我一直想知道解决方案可能是什么,并提出了一些选择:

  1. 使用Context 绕过此行为。但是,除非您有充分的理由,否则通常不鼓励使用 Context + 绕过该问题感觉像是一种肮脏的黑客行为。
  2. 强制QueryRenderer 使用与以前相同的readyState 重新渲染。这也许可以使用refs 来实现,但您需要自己检查何时重新渲染。
  3. 不知何故让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}
/>

有什么想法吗?

【问题讨论】:

    标签: reactjs relayjs relay relaymodern


    【解决方案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 也会重新渲染

    【讨论】:

      猜你喜欢
      • 2018-05-12
      • 2018-01-28
      • 1970-01-01
      • 2019-10-28
      • 2019-06-02
      • 2020-04-09
      • 1970-01-01
      • 2019-11-14
      • 2018-03-27
      相关资源
      最近更新 更多