Использование Refetch с Apollo для повторного отображения запроса и компонента - PullRequest
0 голосов
/ 30 июня 2018

У меня проблемы с регидратацией компонента новыми данными с помощью запроса. Чтобы установить предпосылку, у меня есть два компонента, которые являются родными братьями как это:

<Container>
 <Navbar />
 <Login /> || <Home />
</Container

В основном, в моем компоненте входа в систему у меня мутация, которая запускается следующим образом, когда я нажимаю кнопку входа в систему:

this.props.mutate({
        variables: { token },
        refetchQueries: () =>  ['isAuthenticated']
    }).then((data) => {
      console.log(data);
      this.props.history.push(`/`);
    })

Таким образом, в результате получается, что ничего не воспроизводится, я console.log () в своих компонентах навигации, чтобы увидеть, изменились ли реквизиты для него, но это не изменилось, однако в моей вкладке сети и кеше есть данные, которые он должен возвращать.

Мой компонент элемента навигации выглядит следующим образом:

import React, { Component } from "react";
import { Link, withRouter } from "react-router-dom";
import gql from "graphql-tag";
import { graphql, compose } from "react-apollo";
import { withStyles } from "@material-ui/core/styles";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import Button from "@material-ui/core/Button";
import headerLinksStyle from "./HeaderLinksStyle";
import { LockOpen, GetApp, Info } from "@material-ui/icons";

const isLoggedInQuery = gql`
  query isLoggedInQuery {
    token @client
  }
`;

const loggedInMutation = gql`
  mutation authToken($token: String!) {
    assignAuthToken(token: $token) @client {
      token
    }
  }
`;

const userQuery = gql`
  query isAuthenticated {
    currentUser {
      id
      firstName
      lastName
      gender
      location
      password
      email
      permissions {
        id
        name
        displayOrder
        description
      }
      roles {
        id
        name
        description
        displayOrder
      }
    }
  }
`;

class HeaderLinks extends Component {
  logout = () => {
    localStorage.removeItem("auth_token");
    this.props.mutate({
      variables: { token: null }
    });
    this.props.history.push(`/`);
  };

  refetch = () => {
    console.log("refetch")
    this.props.user.refetch();
  }
  render() {
    const { classes } = this.props;
    const { token } = this.props.data;
    const isLoggedIn = token;
    console.log(this.props);
    return (
      <List className={classes.list}>
        {!isLoggedIn && (
          <ListItem className={classes.listItem}>
            <Link to="/login" style={{ color: "inherit" }}>
              <Button color="inherit" className={classes.navLink}>
                <LockOpen className={classes.icon} />Login
              </Button>
            </Link>
          </ListItem>
        )}
        {!isLoggedIn && (
          <ListItem className={classes.listItem}>
            <Link to="/signup" style={{ color: "inherit" }}>
              <Button color="inherit" className={classes.navLink}>
                <GetApp className={classes.icon} />Sign up
              </Button>
            </Link>
          </ListItem>
        )}
        <ListItem className={classes.listItem}>
            <Button color="inherit" className={classes.navLink} onClick={() => { this.refetch();}}>
              <Info className={classes.icon} />About
            </Button>
        </ListItem>
        {isLoggedIn && (
          <ListItem className={classes.listItem}>
            <Button
              color="inherit"
              className={classes.navLink}
              onClick={event => {
                this.logout();
              }}
            >
              <LockOpen className={classes.icon} />Logout
            </Button>
          </ListItem>
        )}
      </List>
    );
  }
}

export default compose(
  graphql(isLoggedInQuery),
  graphql(loggedInMutation),
  graphql(userQuery, { name: "user", options: {fetchPolicy: 'network-only'}}),
  withStyles(headerLinksStyle),
  withRouter
)(HeaderLinks);

Запуск this.props.user.refetch () работает нормально, однако мои реквизиты возвращаются с устаревшей информацией / ошибкой или данными.

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Вы вообще используете инструмент graphiql? У вас должен быть запрос на currentUser, который вы импортируете здесь в папке queries. Вы также должны иметь мутацию Logout в папке mutations и импортировать ее тоже. Таким образом, вы можете использовать более чистый вкладыш в конце HeaderLinks примерно так: export default graphql(mutation)(graphql(query)(HeaderLinks)); И это только для начинающих. Я рекомендую рефакторинг так:

import React, { Component } from 'react';
import { graphql } from 'react-apollo';
import { Link } from 'react-router';
import query from '../queries/CurrentUser';
import mutation from '../mutations/Logout';

class HeaderLinks extends Component {
  onLogoutClick() {
    this.props.mutate({});
  }

  renderButtons() {
    const { loading, user } = this.props.data;
    if (loading) {
      return <div />;
    }
    if (user) {
      return (
        <li>
          <a onClick={this.onLogoutClick.bind(this)}>Logout</a>
        </li>
      );
    } else {
      return (
        <div>
          <li>
            <Link to="/signup">Signup</Link>
          </li>
          <li>
            <Link to="/login">Login</Link>
          </li>
        </div>
      );
    }
  }

  render() {
    return (
      <nav>
        <div className="nav-wrapper">
          <Link to="/" className="brand-logo left">
            Home
          </Link>
          <ul className="right">{this.renderButtons()}</ul>
        </div>
      </nav>
    );
  }
}

export default graphql(mutation)(graphql(query)(Header));

Теперь вышесказанное предполагает материализацию CSS для стилизации, возможно, вы используете что-то другое, и это нормально, просто нужно отразить это, но я думаю, что то, что я поделился выше, чище и помогает вам двигаться вперед.

Так что после запуска мутации я скажу, что я хочу, чтобы GraphQL автоматически перевыпускал этот список запросов, даже если это всего лишь один запрос, но я собираюсь передать массив, потому что это то, что, как ожидает от меня помощник, будет происходить так :

class HeaderLinks extends Component {
  onLogoutClick() {
    this.props.mutate({
      refetchQueries: [{}]
    });
  }

Итак, у меня есть только один запрос, который я хочу выполнить, это запрос currentUser, который я импортировал как запрос, и я определю его так:

class HeaderLinks extends Component {
  onLogoutClick() {
    this.props.mutate({
      refetchQueries: [{ query: query }]
    });
  }

Значение ключа идентично именам переменных, так что мы можем сжать их до простого запроса:

class HeaderLinks extends Component {
  onLogoutClick() {
    this.props.mutate({
      refetchQueries: [{ query }]
    });
  }

Таким образом, после того, как мутация запустится, повторно запустите этот запрос и заново отрендерируйте любой компонент, связанный с этим запросом, и заголовок должен автоматически обновиться на экране.

0 голосов
/ 03 июля 2018

Это может не ответить на ваш вопрос при повторной загрузке запроса, но рекомендуется использовать client.resetStore() для действия входа в систему. Поскольку вы, вероятно, захотите, чтобы любые результаты, кэшированные в Apollo Store, были повторно получены после входа пользователя в систему.

Это также должно исправить любые проблемы повторного рендеринга компонентов, зависящих от данных ваших запросов.

Компоненты будут повторно отображаться только в том случае, если они получают результаты запроса в качестве реквизита.

...