javascript - React Apollo - 子项未根据结果更改进行更新

标签 javascript reactjs react-apollo

我正在使用 React Apollo 来处理 GaphQL 后端。我正在创建的功能允许用户编辑另一个用户的管理权限。

我有两个组件。一个组件包含 React Apollo 逻辑,包括查询和突变组件。当渲染此组件时,从路由器中的匹配参数传递下来的 prop 指定要获取 GraphQL 查询中使用的权限的管理员。当检索管理权限组件所需的数据时,它将作为 props 传递给子组件,子组件根据 props 设置初始状态。子组件不包含 React Apollo 逻辑,仅包含复选框和其他输入,这些输入在组件状态发生更改时更新它们。单击“保存更改”按钮时,将调用父级的突变函数,传递新更新的权限以将变量插入突变查询中。

我面临的问题是,有时状态不会根据 Prop 而改变。例如,访问admin 1,然后当单击按钮访问admin 2时,路由器会更新URL。到此为止。然后,当单击按钮访问 admin 1 时,路由器会再次更新 URL,尽管 props 已使用新值更新,但 admin 2 仍显示在子组件中。请注意,子组件的构造函数不会再次被调用。

关于如何确保 GraphQL 查询生成的数据显示正确的子组件实例,有什么建议吗?此外,关于如何改进该组件的结构的任何建议。

render(){
if(this.props.steamID ===  null) return null;

const QUERY_VARIABLES = {
  serverID: this.props.serverID,
  selectedAdminSteamID: this.props.steamID,
  currentAdminSteamID: Auth.claim.steamID
};

return (
  <Query
    query={QUERY}
    variables={QUERY_VARIABLES}
  >
    {({ loading, error, data }) => {
      if (loading) return ( ... );
      if (error) return ( ... );
      if(!data.server.selectedAdmin) return ( ... );

      return (
        <Mutation
          mutation={MUTATION}
          update={(cache, { data: { updateAdminPermission } }) => {
            const data = cache.readQuery({ query: QUERY, variables: QUERY_VARIABLES });
            data.server.selectedAdmin = updateAdminPermission;
            cache.writeQuery({ query: QUERY, variables: QUERY_VARIABLES, data: data, });
          }}
        >

          {(updateAdminPermission, { loading, error }) => (
            <>
              <AdminPermissions
                serverID={this.props.serverID}
                steamID={this.props.steamID}

                selectedAdmin={data.server.selectedAdmin}
                currentAdmin={data.server.currentAdmin}

                updatePermissionFunction={(variables) => {
                  updateAdminPermission({ variables })
                }}
                updatePermissionLoading={loading}
              />
              <GraphQLErrorModal error={error} />
            </>
          )}

        </Mutation>
      );
    }}
  </Query>
);
}

class AdminPermissions extends React.Component{
    constructor(props){
      super();

      this.state = props.selectedAdmin;

      this.guid = React.createRef();
      this.updatePermission = this.updatePermission.bind(this);
      this.saveChanges = this.saveChanges.bind(this);
    }

    updatePermission(changedPermission, value){
      if(changedPermission === 'manageAssignPermissions' && value > 0){
        for(let permission of panelPermissions.concat(gamePermissions)){
          if(permission.permission === 'manageAssignPermissions') continue;
          this.setState({ [permission.permission]: 2 });
        }
      }
      this.setState({ [changedPermission]: value });
    }

    saveChanges(){
      this.props.updatePermissionFunction({
        serverID: this.props.serverID,
        steamID: this.props.steamID,
        guid: this.guid.current.value,
        ...this.state
      });
    }

    render(){
        // renders pairs of checkboxes with checked value based on state and on change event that calls update permissions method passing the name of the associated permission and a value that is calculated based on which boxes in the pair are ticked.
    }
 }

查询(更新)

  query AdminPermission($serverID: Int!, $selectedAdminSteamID: String!, $currentAdminSteamID: String!) {
    server(id: $serverID) {
      id

      selectedAdmin: adminPermission(steamID: $selectedAdminSteamID) {    
        _id

        admin {
          _id

          steamID
          displayName
          avatar
        }

        player {
          _id
          guid
        }

        manageAssignPermissions
        viewAdminPermissions
        ...
      }
      currentAdmin: adminPermission(steamID: $currentAdminSteamID) {
        _id

        admin {
          _id
          steamID
        }

        manageAssignPermissions
        viewAdminPermissions
        ...
      }
    }
  }

最佳答案

您必须设置 QueryfetchPolicycache-and-network ,默认为cache-first :

<Query
    query={QUERY}
    variables={QUERY_VARIABLES}
    fetchPolicy='cache-and-network'
  >

如果您阅读 documentation :

  • cache-first: This is the default value where we always try reading data from your cache first. If all the data needed to fulfill your query is in the cache then that data will be returned. Apollo will only fetch from the network if a cached result is not available. This fetch policy aims to minimize the number of network requests sent when rendering your component.

  • cache-and-network: This fetch policy will have Apollo first trying to read data from your cache. If all the data needed to fulfill your query is in the cache then that data will be returned. However, regardless of whether or not the full data is in your cache this fetchPolicy will always execute query with the network interface unlike cache-first which will only execute your query if the query data is not in your cache. This fetch policy optimizes for users getting a quick response while also trying to keep cached data consistent with your server data at the cost of extra network requests.

关于javascript - React Apollo - 子项未根据结果更改进行更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56295083/

相关文章:

javascript - 使用 GM xmlhttpRequest 而不是 iframe 来显示来自外部页面的相关信息

javascript - 如何在延迟解决后延迟执行 promise

javascript - 链接内元素的 stopPropagation/preventDefault 行为

javascript - react 。如何从父组件调用组件的方法

reactjs - React Router v4 - 使用不同的查询参数重定向到相同的路由

javascript - 不是 Electron chrome 中的函数,但不是 Node 控制台中的函数

node.js - 如何在运行reactjs+meteor应用程序时禁用控制台日志

apollo - `data` 在 apollo useMutation Promise 中未定义

react-apollo - 使用 useMutation 可能出现未处理的 promise 拒绝警告

使用单独的数据服务器测试 apollo graphql 容器