Как заставить 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
не обращает внимания на изменения реквизита родителя, создает довольно большую проблему. Мне было интересно, каким может быть решение для этого, и придумал несколько вариантов:
- Используйте контекст, чтобы обойти это поведение. Однако, как правило, не рекомендуется использовать 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-компонентом, и вам обычно не нужно оборачивать его в класс Component render.
Список теперь является компонентом функции Pure, и когда он получает новые реквизиты (parentProps), он будет перерисовываться, следовательно, таблица с перерисовывается.