javascript - 中继现代 RefetchContainer Prop 未传递给组件

标签 javascript react-redux graphql relayjs relaymodern

我在 Relay Modern 中设置 refetchContainer 时遇到一些问题。父组件是 QueryRenderer,它运行初始查询,适本地填充子组件的 Prop (a-prop-riately?嗯?嗯?!)。 refetchContainer 指定了我们所有的变量,并在输入字段的 onChange 事件上,使用新变量重新运行查询。这一切都很完美,除了 child 的 Prop 永远不会用收到的新数据更新。我可以深入中继存储并查看确实收到了带有适当数据的查询。一段时间以来我一直在反对这个问题,我会很感激一些帮助。可能我缺少一些简单的东西。上帝知道 Relay Modern 文档很少。

我四处寻找,找不到合适的解决方案。这个人似乎有类似的问题: relay refetch doesn't show the result

带有QueryRenderer的父组件:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { graphql, QueryRenderer } from 'react-relay';
import Search from './Search';

const propTypes = {
  auth: PropTypes.object.isRequired,
};

class SearchContainer extends Component {
  render() {
    return (
      <QueryRenderer
        query={graphql`
          query SearchContainerQuery($search: String!){
            users: searchUsers(search:$search, first:10){
              ...Search_users
            }
          }`}
        variables={{ search: 'someDefaultSearch' }}
        environment={this.props.auth.environment}
        render={({ error, props }) => {
          if (error) {
            console.log(error);
          }
          if (props) {
            return <Search users={props.users} />;
          }
          return <div>No Dice</div>;
        }}
      />
    );
  }
}

SearchContainer.propTypes = propTypes;

export default connect(state => ({ auth: state.auth }))(SearchContainer);

带有createRefetchContainer的子组件:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { createRefetchContainer, graphql } from 'react-relay';

const propTypes = {
  relay: PropTypes.object.isRequired,
  users: PropTypes.object,
};

const defaultProps = {
  users: {},
};

class Search extends Component {
  render() {
    return (
      <div>
        <input
          type="text"
          onChange={(e) => {
            e.preventDefault();
            this.props.relay.refetch({
              search: e.target.value,
            });
          }}
        />
        <ul>
          {this.props.users.nodes.map(user =>
            <li key={user.id}>{user.username}</li>,
          )}
        </ul>
      </div>
    );
  }
}

Search.propTypes = propTypes;
Search.defaultProps = defaultProps;

export default createRefetchContainer(
  Search,
  {
    users: graphql.experimental`
      fragment Search_users on SearchUsersConnection
      @argumentDefinitions(
        search: {type: "String", defaultValue: ""}
      ) {
        nodes {
            id
            displayName
            username
          }
      }
    `,
  },
  graphql.experimental`
    query SearchRefetchQuery($search: String!) {
      users: searchUsers(search:$search, first:10){
        ...Search_users @arguments(search: $search)
      }
    }
  `,
);

GraphQL 看起来像这样:

# A connection to a list of `User` values.
type SearchUsersConnection {
  # Information to aid in pagination.
  pageInfo: PageInfo!

  # The count of *all* `User` you could get from the connection.
  totalCount: Int

  # A list of edges which contains the `User` and cursor to aid in pagination.
  edges: [SearchUsersEdge]

  # A list of `User` objects.
  nodes: [User]
}

适本地进行网络调用,并按预期返回数据。 NetworkCalls

@arguments 指令似乎可以从此处的重新获取查询中省略:

query SearchRefetchQuery($search: String!) {
      users: searchUsers(search:$search, first:10){
          ...Search_users @arguments(search: $search)
      }
}

(去掉好像没有效果)

我已尝试按照此处的建议将 @arguments 指令添加到父组件的片段:Pass variables to fragment container in relay modern , 没有效果。

最佳答案

如其他答案中所述,这实际上是预期的行为,我将尝试稍微扩展一下答案。

当调用 refetch 并执行 refetchQuery 时,Relay 实际上并不使用查询结果来重新渲染组件。它所做的只是将有效负载规范化到商店中并触发任何相关订阅。这意味着如果获取的数据与已安装容器订阅的数据无关(例如,使用完全不同的没有任何数据重叠的节点 ID),则组件将不会重新呈现。

在这种特定情况下,容器不重新呈现的原因,即为什么它没有订阅 refetchQuery 触发的更改,是由于订阅的设置方式.订阅基本上是对快照的订阅,它基本上表示一个具体的片段以及在给定时间点与其关联的数据和记录——当与快照关联的记录发生变化时,订阅对于该快照,将收到更改通知。

在这种情况下,假设容器的片段没有变量,它将订阅的快照将只与初始节点相关联;在重新获取发生并且存储更新后,新节点的记录将被更新,但与原始快照关联的记录没有改变,因此订阅它的容器不会收到通知。

这意味着 Refetch 容器仅在您更改组件片段中的变量时才真正使用。此处提供的解决方案是有效的,即在重新获取容器的片段中包含变量或在 QueryRenderer 中设置新变量上一级。

这肯定可以在文档中更加清楚,所以我会更新它们以反射(reflect)这一点。希望对您有所帮助!

关于javascript - 中继现代 RefetchContainer Prop 未传递给组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45245653/

相关文章:

php - 图像不闪烁

javascript - 嵌套对象过滤 - Angular

javascript - React Redux 状态不替换

reactjs - 映射调度到属性 : any point?

reactjs - 使用 Netlify CMS 的 Gatsby 镜像 - 字段 "image"不得有选择,因为类型 "String"没有子字段

javascript - 删除 javascript 字符串中的变音符号或特殊字符

javascript - 如何使用 viewbag 在 View 页面中显示警报消息

javascript - 在 React 路由中将 Props 传递给组件

GraphQL 异步查询结果

react-native - 连接到多个组件时的 Apollo 客户端查询和数据存储