Состояние общего ресурса магазина Apollo между компонентами - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть заголовок, который переключается между отображением ссылок Login/Signup в состояние Logout в зависимости от того, может ли он запросить объект пользователя (в основном, указывая, есть ли в заголовке jwt).

Вот где я застрял: при загрузке страницы компонент Header извлекает информацию о пользователе, если он не возвращает данные, то я знаю, что отображаются ссылки Login/Signup.

Итак, я нажимаю на ссылку «Вход в систему», заполняю форму и успешно захожу в систему. Я хочу, чтобы триггер заголовка перезагружал информацию о пользователе. В идеале он будет проверять локальный кеш на основе информации о пользователе, возвращаемой при входе в систему.

Я привык к настроению Redux, поэтому чувствую, что упускаю что-то фундаментальное в управлении состоянием Аполлона.

вот пример кода: Header.js

const USER_QUERY = gql`
  {
    user {
      id
      email
    }
  }
`;

const LOGOUT_MUTATION = gql`
  mutation LogoutMutation {
    logout {
      message
    }
  }
`;

const Header = () => (
  <div className="header">
    header

    <Query query={USER_QUERY}>
      {({ loading, error, data }) => {
        if (loading) return <div>Fetching</div>;
        if (error) {
          return (
            <div>
              <Link to="signup">Signup</Link>
              <Link to="login">Login</Link>
            </div>
          );
        }

        return (
          <div>
            {data.user.email}
            <Mutation
              mutation={LOGOUT_MUTATION}
            >
              {
                mutation => <button type="submit" onClick={mutation}>Logout</button>
              }
            </Mutation>
          </div>
        );
      }}
    </Query>

  </div>
);

Auth.js

const SIGNUP_MUTATION = gql`
  mutation SignupMutation($name: String!, $email: String!, $password: String!) {
    signup(name: $name, email: $email, password: $password) {
      id
      name
      email
    }
  }
`;

const LOGIN_MUTATION = gql`
  mutation LoginMutation($email: String!, $password: String!) {
    login(email: $email, password: $password) {
      id
      name
      email
    }
  }
`;

class Auth extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      email: '',
      password: '',
      name: '',
      isSignup: props.type === 'SIGNUP',
    };
  }

  render() {
    const {
      email,
      password,
      name,
      isSignup,
    } = this.state;

    return (
      <div>
        <h1>{isSignup ? 'Sign Up' : 'Log In'}</h1>

        <Mutation
          mutation={isSignup ? SIGNUP_MUTATION : LOGIN_MUTATION}
          variables={isSignup ? { name, email, password } : { email, password }}
          onCompleted={(res) => { console.log('complete', res); }}
        >
          {
            (mutation, { error }) => (
              <form
                onSubmit={(e) => {
                  e.preventDefault();
                  mutation();
                }}
              >
                {
                  isSignup
                  && (
                    <React.Fragment>
                      <label htmlFor="auth-name">name</label>
                      <input
                        value={name}
                        onChange={e => this.setState({ name: e.target.value })}
                        type="text"
                        placeholder="name"
                        id="auth-name"
                      />
                    </React.Fragment>
                  )
                }
                <label htmlFor="email">email</label>
                <input
                  value={email}
                  onChange={e => this.setState({ email: e.target.value })}
                  type="text"
                  placeholder="email"
                  id="auth-email"
                />

                <label htmlFor="password">password</label>
                <input
                  value={password}
                  onChange={e => this.setState({ password: e.target.value })}
                  type="password"
                  placeholder="password"
                  id="auth-password"
                />

                <button type="submit">Submit</button>
                { error && <div>ERROR Authenticating</div>}
              </form>
            )
          }
        </Mutation>
      </div>
    );
  }
}

1 Ответ

0 голосов
/ 15 сентября 2018

В вашем компоненте Header вы не должны использовать параметр error компонента Query, чтобы определить, вошел ли пользователь в систему. Этот параметр предназначен для обработки ошибок graphql, ошибок сервера и не быть "нормальным" путем выполнения в вашем приложении.

Теперь вы должны решить, что делать с состоянием «isLoggedIn», прежде чем пытаться выполнить его.

Из того, что я понял, вы решили, что ваше состояние "isLoggedIn" было сохранено в URL. Иными словами, единственный источник правды, который сообщает вам, вошел ли пользователь в систему или нет, находится в URL.

Оттуда у вас есть различные варианты хранения, каждый со своими преимуществами и недостатками, которые я не буду здесь обсуждать:

  • Держите его в URL
  • Хранить в местном хранилище
  • Использовать jwt cookie
  • Использовать Контекст реагирования
  • Использовать apollo-link-state
  • ... любой другой вариант хранения, который станет «источником правды»
...