Реагировать Аполлон - ребенок не обновляется в зависимости от изменения результата - PullRequest
0 голосов
/ 24 мая 2019

Я использую React Apollo для работы с бэкэндом GaphQL.Функция, которую я создаю, позволяет пользователям редактировать права администратора другого пользователя.

У меня есть два компонента.Один компонент содержит логику React Apollo, включая запрос и компоненты мутации.Когда этот компонент визуализируется, свойство, которое передается из параметра соответствия в маршрутизаторе, указывает, какой администратор для получения разрешений которого используется в запросе GraphQL.Когда данные, необходимые для компонента прав доступа администратора, извлекаются, они передаются в качестве подпорки дочернему компоненту, который устанавливает начальное состояние на основе подпорки.Дочерний компонент не содержит логику React Apollo и просто содержит флажки и другие входные данные, которые обновляют состояние компонента по мере его изменения.При нажатии кнопки «Сохранить изменения» вызывается функция мутации родителя, передавая недавно обновленные разрешения на вставку переменных в запрос на мутацию.

Проблема, с которой я сталкиваюсь, заключается в том, что иногда состояние не изменяется в зависимости от реквизита.Например, доступ к admin 1, маршрутизатор затем обновляет URL при нажатии кнопки для доступа к admin 2. Это работает до этого момента.Затем маршрутизатор снова обновляет URL-адрес при нажатии кнопки для доступа к admin 1, 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
        ...
      }
    }
  }

1 Ответ

1 голос
/ 24 мая 2019

Вы должны установить Query fetchPolicy на cache-and-network, по умолчанию это cache-first:

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

Если вы прочитали документацию :

  • cache-first : это значение по умолчанию, при котором мы всегда пытаемся прочитать данные из вашего кэша в первую очередь. Если все данные, необходимые для выполнения вашего запрос находится в кеше, тогда эти данные будут возвращены. Аполлон будет извлекать из сети только в том случае, если кэшированный результат недоступен. это политика извлечения направлена ​​на минимизацию количества сетевых запросов, отправляемых при рендеринг вашего компонента.

  • кэш-и-сеть : эта политика выборки будет Аполлон сначала пытается прочитать данные из вашего кеша. Если все данные необходимо выполнить ваш запрос в кеше, то эти данные будут вернулся. Однако независимо от того, находятся ли полные данные в ваш кеш этот fetchPolicy всегда будет выполнять запрос с сетью интерфейс в отличие от кеш-первого, который будет выполнять ваш запрос, только если Данные запроса не в вашем кэше. Эта политика получения оптимизирует для пользователей получить быстрый ответ при попытке сохранить кэшированные данные в соответствии с данными вашего сервера за счет дополнительной сети запросы.

...