Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-Native: Formik ref fails to get value

I have a dummy Login code with formik form in react-native

import React, { Component } from "react";
import {
  TextInput,
  Text,
  Alert,
  Image,
  View,
  TouchableOpacity,
  SafeAreaView,
  ScrollView
} from "react-native";
import styles from "./Styles/LoginStylesheet";
import { KeyboardAccessoryNavigation } from "react-native-keyboard-accessory";
import { Formik } from "formik";
import schemaObject, { initialValues, refs } from "./Validations/LoginValidations";

export default class LoginView extends Component {

  constructor(props) {
    super(props);
    this.state = {
      activeInputIndex: 0
    };
  }

  handleFocus = index => () => {
    this.setState({
      activeInputIndex: index
    });
  };

  handleFocusNext = () => {
    if (this.state.activeInputIndex + 1 >= refs.length) {
      return;
    }
    refs[this.state.activeInputIndex + 1].focus();
  };

  handleFocusPrevious = () => {
    if (this.state.activeInputIndex - 1 < 0) {
      return;
    }
    refs[this.state.activeInputIndex - 1].focus();
  };

  handleLogin = () => {
    console.log("ACTIOn");
      // this.formik.handleSubmit();
  };

  render() {
    return (
      <View style={styles.safeAreaView}>
        <SafeAreaView style={styles.safeAreaView}>
          <ScrollView style={styles.superView}>
            <Formik {/* LINE 56  */}
              initialValues={initialValues}
              onSubmit={values => Alert.alert(JSON.stringify(values))}
              validationSchema={schemaObject}
              ref={p => (this.formik = p)}
            >
              {({
                values,
                handleChange,
                errors,
                setFieldTouched,
                touched,
                isValid,
                handleSubmit
              }) => (
                <View style={styles.superView}>
                  <View style={styles.logoParentView}>
                    <Image
                      source={require("../../Resources/Assets/Login/aptihealth_logo.png")}
                      resizeMode={"contain"}
                      style={styles.logo}
                    />
                  </View>

                  <View style={styles.emailParentView}>
                    <Text style={styles.titleLabel}>Email Id</Text>
                    <TextInput
                      value={values.emailId}
                      onChangeText={handleChange("emailId")}
                      onBlur={() => setFieldTouched("emailId")}
                      placeholder="Email Id"
                      style={styles.textInput}
                      autoCorrect={false}
                      onFocus={this.handleFocus(0)}
                      ref={input => {
                        refs[0] = input;
                      }}
                    />
                    {touched.emailId && errors.emailId && (
                      <Text style={{ fontSize: 10, color: "red" }}>
                        {errors.emailId}
                      </Text>
                    )}
                  </View>

                  <View style={styles.passwordParentView}>
                    <Text style={styles.titleLabel}>Password</Text>
                    <TextInput
                      value={values.password}
                      onChangeText={handleChange("password")}
                      placeholder="Password"
                      onBlur={() => setFieldTouched("password")}
                      style={styles.textInput}
                      autoCorrect={false}
                      secureTextEntry={true}
                      onFocus={this.handleFocus(1)}
                      ref={input => {
                        refs[1] = input;
                      }}
                    />
                    {touched.password && errors.password && (
                      <Text style={{ fontSize: 10, color: "red" }}>
                        {errors.password}
                      </Text>
                    )}
                  </View>

                  <View style={styles.forgotPasswordParentView}>
                    <TouchableOpacity
                      style={styles.forgotpasswordButton}
                      activeOpacity={0.7}
                    >
                      <Text>Forgot Password?</Text>
                    </TouchableOpacity>
                  </View>

                  <View style={styles.loginParentView}>
                    <TouchableOpacity
                      onPress={() => {
                        console.log("VALUES: ", values, this.formik);
                        this.handleLogin();
                      }}
                      style={styles.loginButton}
                      activeOpacity={0.7}
                    >
                      <Text style={styles.loginText}>Login</Text>
                    </TouchableOpacity>
                  </View>

                  <View style={styles.seperaterParentView}>
                    <View style={styles.seperaterView} />
                    <Text style={styles.seperaterText}>OR</Text>
                    <View style={styles.seperaterView} />
                  </View>

                  <View style={styles.faceIdLoginParentView}>
                    <Image
                      source={require("../../Resources/Assets/face_id_small_color/face_id_small_color.png")}
                      resizeMode={"contain"}
                    />
                    <TouchableOpacity style={styles.faceIdButton}>
                      <Text>Sign In with Face ID</Text>
                    </TouchableOpacity>
                  </View>
                  <View style={styles.signUpParentView}>
                    <TouchableOpacity style={styles.signupButton}>
                      <Text>Sign Up for Account Here</Text>
                    </TouchableOpacity>
                  </View>
                </View>
              )}
            </Formik>
          </ScrollView>
        </SafeAreaView>
        <KeyboardAccessoryNavigation
          nextDisabled={false}
          previousDisabled={false}
          nextHidden={false}
          previousHidden={false}
          onNext={this.handleFocusNext}
          onPrevious={this.handleFocusPrevious}
          avoidKeyboard
        />
      </View>
    );
  }
}

I am trying to console formik ref in login action getting undefined value with debug error

ExceptionsManager.js:126 Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of `LoginView`.
    in Formik (at LoginView.js:56)

I have no idea why it's getting undefined ??

like image 779
Abhishek Thapliyal Avatar asked Dec 23 '19 15:12

Abhishek Thapliyal


People also ask

How do I get field value in Formik?

Formik uses the name prop to connect the input to values . If it's in an Array, then your index is just another dot-notation path. You use that same name path to access the data.

What is Formik dirty?

Returns true if values are not deeply equal from initial values, false otherwise. dirty is a readonly computed property and should not be mutated directly.

Does Formik work with React Native?

Formik is 100% compatible with React Native and React Native Web. However, because of differences between ReactDOM's and React Native's handling of forms and text input, there are some differences to be aware of.

What does Formik handleChange do?

Using Formik's handleChange The handleChange method updates the form values based on the input's name attribute that was changed. The handleChange method is used with input elements. Field component internally updates the values without the need of implementing the handleChange method.

What is formik in React Native?

Formik is an open-source React and React Native library that allows us to handle forms by: handling form submission via reusable methods and handlers (such as handleChange, handleBlur, and handleSubmit ); handling validation and error messages out of the box.

How do you handle forms in React Native?

This can vary from handling form state, input field validation, handling errors, form submission, and so on. Formik is an open-source React and React Native library that allows us to handle forms by: handling form submission via reusable methods and handlers (such as handleChange, handleBlur, and handleSubmit );

What is the best form control library in react?

However our Top pick today: Formik + Yup. F ormik is a form control libs using controlled components in React. It’s gaining popularity and currently achieving 21.5k stars on GitHub. It helps take care of repetitive form events like tracking values, errors, and touched fields.

What is usefield() in react formik?

34 {meta.touched && meta.error ? ( 47 {meta.touched && meta.error ? ( As you can see above, useField () gives us the ability to connect any kind input of React component to Formik as if it were a <Field> + <ErrorMessage>. We can use it to build a group of reusable inputs that fit our needs. Congratulations!


1 Answers

You should take a look at this issue.

You problem is here

<Formik
  initialValues={initialValues}
  onSubmit={values => Alert.alert(JSON.stringify(values))}
  validationSchema={schemaObject}
  ref={p => (this.formik = p)} {/* passing this ref will throw the error */}
>

In the latest version of Formik, they changed Formik to a functional component as explained in the issue, which gives you this error if you pass ref's.

You can check for the suggestions on the issue or wait until they release an update with the correction.

Edit:

Formik made an update and now you can use ref with the prop innerRef.

Please see this comment

You should change it to

<Formik
  initialValues={initialValues}
  onSubmit={values => Alert.alert(JSON.stringify(values))}
  validationSchema={schemaObject}
  {/* using innerRef instead of ref*/}
  innerRef={p => (this.formik = p)} {/* this will give you the formik bag */}
>

And this way you can call this.formik.handleSubmit(), just lik you want to do.

like image 123
Vencovsky Avatar answered Oct 18 '22 23:10

Vencovsky