@vapersan

Почему выполняется запрос при повторной отрисовке компонентов?

Шаги воспроизведения бага:
1. Введите незарегистрированный номер телефона (+ можете не вводить пароль)
2. Нажмите кнопку войти
3. Стирайте по одному символу из инпута с номером телефона

В чём выражается баг:
Каждый раз когда изменяется значение ипута (уже после нажатия на кнопку "войти") меняется стейт и почему-то происходит запрос

Почему происходит запрос? Ведь запрос никак не связан с жизненным циклом компонента, он не должен вызываться при перерисовке и при изменении стейта в том числе.

Код

import React, {Component} from 'react';
import {Button, Card, Elevation, FormGroup, InputGroup, Tooltip} from "@blueprintjs/core";
import classes from "../regByPhone/regByPhone.module.scss";
import {Layout} from "../common";
import classesCommon from "../common/common.module.scss";
import {Link} from "react-router-dom";
import {gql, useLazyQuery} from "@apollo/client";

class Login extends Component {
  constructor(props, context) {
    super(props, context);
    this.state = {
      phone: "",
      password: "",
      formErrorText: ""
    };
  }

  handleLoginPhoneInput({target: {value: phone}}) {
    this.setState({phone});
  };

  handleLoginLockClick() {
    this.setState((prevState) => ({
      showPassword: !prevState.showPassword,
    }));
  };

  render() {
    const {showPassword, phone, password, isFormNotValid} = this.state,
      {onAuth} = this.props;

    return (
      <Layout>
        <Card elevation={Elevation.TWO} className={classesCommon.card}>
          <FormGroup helperText={this.state.phoneErrorText}>
            <InputGroup
              className={classes.phone_input}
              large
              placeholder="Введите Ваш номер телефона"
              value={phone}
              onChange={this.handleLoginPhoneInput.bind(this)}
              maxLength={11}
            />
          </FormGroup>
          <FormGroup helperText={this.state.passwordErrorText}>
            <InputGroup
              className={classes.pass_input}
              large
              placeholder="Введите пароль"
              rightElement={<LockButton showPassword={showPassword} onClick={this.handleLoginLockClick.bind(this)}/>}
              type={showPassword ? "text" : "password"}
              value={password}
              onChange={this.handleLoginPasswordInput.bind(this)}
            />
          </FormGroup>
          <p>{this.state.formErrorText}</p>
          <Link to="/registration-by-phone">Регистрация</Link>
          <LoginButton phone={phone} password={password} isFormNotValid={isFormNotValid} onAuth={onAuth}/>
        </Card>
      </Layout>
    );
  }
}

const LOGIN = gql`
    query login($login: String!, $pwd: String!) {
        login(login: $login, pwd: $pwd) {
            id, userName, surname, firstname, middlename, email, phone
        }
    }
`;

function LoginButton({phone, password, isFormNotValid, onAuth}) {

  const [getLogin, {loading, data}] = useLazyQuery(LOGIN, {variables: {login: phone, pwd: password}});

  if (data?.login != null) {
    onAuth(data.login)
  }

  return <Button
    className={classes.enter}
    large
    disabled={isFormNotValid}
    onClick={getLogin}
  >
    Войти
  </Button>
}

export default Login;

  • Вопрос задан
  • 55 просмотров
Решения вопроса 1
@vapersan Автор вопроса
5ffef6fb59eee003775756.png
В общем и целом. Вот решение.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Fi1osof
@Fi1osof
JS fullstack developer
Вряд ли здесь бага графа.

Скорее всего у вас где-то логическая ошибка. Почему так говорю? Потому что вы в data?.login != null используете != (не строгое сравнение). Старайтесь максимально использовать нестрогое сравнение, иначе вы привыкаете к неточностям. Если вы в данном случае хотите явно сравнивать нестрого, тогда хотя бы пишите if(!data?.login). Хотя это тоже не строгое сравнение, но так более принято.

Во-вторых, у вас
if (data?.login != null) {
onAuth(data.login)
}
выполняется при каждом рендеринге. Так как у вас в этот момент логин не пустой, у вас каждый раз срабатывает метод onAuth. Идите посмотрите что в нем.

В-третьих, посмотрите конфиг созданного аполло-клиента, может вы в нем прописали по-умолчанию fetchPolicy: 'network-only' или типа того.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы