Использование языкового запроса, запускаемого onChangeText в React Native

#javascript #android #react-native #graphql #apollo-client

#javascript #Android #react-native #graphql #apollo-клиент

Вопрос:

Я создаю приложение Android React Native с клиентом Apollo, которое подключается к серверной части GraphQL.

Я настроил экран входа в систему, на котором пользователи могут вводить свое имя пользователя и пароль и выполнять запрос для входа при нажатии / нажатии кнопки.

При первой загрузке приложения (или сразу после обновления приложения) все нормально. Ничего необычного, когда я ввожу учетные данные с первой попытки и успешно вхожу в систему. Но после одной неудачной попытки входа в систему (либо из-за ошибки сети, либо из-за неверных учетных данных), каждый раз, когда я набираю или удаляю один символ из любого из текстовых вводов, запрос входа из useLazyQuery выполняется без нажатия кнопки входа. Проблема исчезает только тогда, когда я закрываю и перезапускаю приложение.

Является ли onChangeText причиной этого? Я неправильно использую useLazyQuery? Я что-то здесь упускаю?

Вот код:

 import React, { useState, useContext, useRef } from 'react';
import { View, Text, TextInput, ToastAndroid } from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { gql, useLazyQuery } from '@apollo/client';
import AsyncStorage from '@react-native-community/async-storage';
import AuthContext from '../context/AuthContext';
import Loading from '../components/Loading';

const LOGIN = gql`
  query Login (
    $username: String!
    $password: String!
  ) {
    login (
      username: $username
      password: $password
    ) {
      token
    }
  }
`;

const Login = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  const { setAuthLoading } = useContext(AuthContext);

  const nextInputRef = useRef();

  const setToken = async (token) => {
    await AsyncStorage.setItem('token', token);
    setAuthLoading(true);
  };

  const [queryLogin, { loading, error, data }] = useLazyQuery(LOGIN);
  if (loading) return <Loading />;
  if (error) ToastAndroid.show(error.message, ToastAndroid.SHORT);
  if (data amp;amp; data.login amp;amp; data.login.token) {
    setToken(data.login.token);
  }

  const sendLogin = () => {
    queryLogin({ variables: { username, password } })
  };

  return (
    <View>
      <TextInput
        value={username}
        onChangeText={(text) => setUsername(text)}
        placeholder="USERNAME"
        returnKeyType="next"
        onSubmitEditing={() => nextInputRef.current.focus()}
      ></TextInput>

      <TextInput
        secureTextEntry={true}
        value={password}
        onChangeText={(text) => setPassword(text)}
        placeholder="PASSWORD"
        returnKeyType="done"
        ref={nextInputRef}
        onSubmitEditing={() => sendLogin()}
      ></TextInput>

      <TouchableOpacity onPress={() => sendLogin()}>
        <Text>LOGIN</Text>
      </TouchableOpacity>
    </View>
  );
};
  

Вот мои связанные версии стека:

 "@apollo/client": "^3.2.1",
"@react-native-community/async-storage": "^1.12.0",
"graphql": "^15.3.0",
"react": "16.13.1",
"react-native": "0.63.2",
"react-native-gesture-handler": "^1.8.0",
  

Комментарии:

1. не объявляйте переменные в hook, передавайте их в onPress

2. @xadm Я попробовал ваш совет, и проблема все еще сохраняется, но что-то изменилось. Он больше не переходит к компоненту <Loading /> каждый раз, когда я что-то печатаю. Так что спасибо за это.

3. почему бы не использовать useMutation ? почему onSubmitEditing={() => sendLogin()} ?

4. @xadm ну, серверный API входа в систему — это запрос. Я не создавал серверный API. В любом случае я изменил метод на useApolloClient , и он сработал. В любом случае спасибо за помощь 🙂