Как заставить QueryRenderer распространять изменения родительских реквизитов?

Используя Relay Modern v.1.4.1, учтите следующее List составная часть.

Требуется два реквизита foo а также bar и оказывает Table компонент с этими реквизитами и результат запроса GraphQL:

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 составная часть foo а также bar установлены правильно, однако если foo или же bar изменить впоследствии новые значения не распространяются на Table компонент из-за QueryRenderer,

Так как QueryRenderer только перерисовывает, если variables за SomeQuery изменить renderQuery Метод не срабатывает, потому что QueryRenderer не видит в этом необходимости, поэтому Table Компонент остается со старыми значениями реквизита.

Поскольку передача реквизита детям является очень распространенной задачей, тот факт, что QueryRenderer не обращает внимания на изменения реквизита родителя, создает довольно большую проблему. Мне было интересно, каким может быть решение для этого, и придумал несколько вариантов:

  1. Используйте контекст, чтобы обойти это поведение. Однако, как правило, не рекомендуется использовать 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}
/>

Есть идеи?

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-компонентом, и вам обычно не нужно оборачивать его в класс Component render.

Список теперь является компонентом функции Pure, и когда он получает новые реквизиты (parentProps), он будет перерисовываться, следовательно, таблица с перерисовывается.

Другие вопросы по тегам