Search code examples
javascriptreact-nativegraphqlapollo

undefined is not an object (evaluating 'event.target.name')


So im trying to make an authentication with react native and graphql apollo and im having some issues with it. This error pops up when i try typing on the name textinput.

SignIn.js

// ... other imports
import { useMutation } from '@apollo/client';
import { useForm } from '../constants/hooks';

const { onChange, onSubmit, values } = useForm(loginUserCallback, {
    name: '',
    password: '',
  });

  const [loginUser, { loading }] = useMutation(mutationData.LOGIN_USER, {
    update(_, { data: { login: userData } }) {
      // context.login(userData);
      navigation.replace('Navigator'); // router.push("/");
      // toast.success(`Logged In Successfully`, { autoClose: 800 });
    },
    onError(err) {
      console.log(err.graphQLErrors[0].extensions.errors);
    },
    variables: values,
  });

  function loginUserCallback() {
    loginUser();
  }

return (
  <View>
    <TextInput
      value={values.name}
      name="name"
      onChangeText={onChange}
      placeholder="Enter User Name"
    />
    <TextInput
      value={values.password}
      name="password"
      onChangeText={onChange}
      placeholder="Enter Password"
    />

    <TouchableOpacity onPress={onSubmit}>
      <Text>SIGN IN</Text>
    </TouchableOpacity>
  </View>
);

hooks.js

import { useState } from 'react';

export const useForm = (callback, initialState = {}) => {
  const [values, setValues] = useState(initialState);

  const onChange = (event) => {
    setValues({ ...values, [event.target.name]: event.target.value });
  };

  const onSubmit = (event) => {
    event.preventDefault();
    callback();
  };

  return {
    onChange,
    onSubmit,
    values,
  };
};

mutationData.js

import { gql } from '@apollo/client';

// =============
// Auth
// =============

const LOGIN_USER = gql`
  mutation login($name: String!, $password: String!) {
    login(name: $name, password: $password) {
      id
      email
      username
      createdAt
      token
    }
  }
`;

const REGISTER_USER = gql`
  mutation register(
    $username: String!
    $email: String!
    $password: String!
    $confirmPassword: String!
  ) {
    register(
      registerInput: {
        username: $username
        email: $email
        password: $password
        confirmPassword: $confirmPassword
      }
    ) {
      id
      email
      username
      createdAt
      token
    }
  }
`;

export default {
  LOGIN_USER,
  REGISTER_USER,
};

Extra Info:

If i miss any details, which i know this is an uninformative post, pls tell in the comments and ill try my best to provide those information, also yes i tried working on the error for a few hours.


Solution

  • Ok I think I've figured out your problem

    One problem is that onChangeText as @Appfred pointed out returns the value not the event

    the second problem is that TextInput doesn't have a name props so it ignore the one you are passing

    you can resolve your problem with a few adjustments.

    in your custom hook you need to change the onChange signature like this

    
      const onChange = (name, value) => {
        setValues({ ...values, [name]: value });
      };
    
    

    and you need to modify your form in this way

    <View>
        <TextInput
          value={values.name}
          onChangeText={value => onChange('name', value)}
          placeholder="Enter User Name"
        />
        <TextInput
          value={values.password}
          onChangeText={value => onChange('password', value)}
          placeholder="Enter Password"
        />
    
        <TouchableOpacity onPress={onSubmit}>
          <Text>SIGN IN</Text>
        </TouchableOpacity>
      </View>
    
    

    or if you preferer a curried function approach you could do

      const onChange = name => value => {
        setValues({ ...values, [name]: value });
      };
    
    

    and then

    <View>
        <TextInput
          value={values.name}
          onChangeText={ onChange('name') }
          placeholder="Enter User Name"
        />
        <TextInput
          value={values.password}
          onChangeText={ onChange('password') }
          placeholder="Enter Password"
        />
    
        <TouchableOpacity onPress={onSubmit}>
          <Text>SIGN IN</Text>
        </TouchableOpacity>
      </View>