Formik: React Native Picker - Type Error

Created on 16 Mar 2019  ·  6Comments  ·  Source: formium/formik

I've been trying to make Picker component of React-Native work for Formik for last three days but getting into issues one after another. After lots of googling around and reading documents, I've come up with below code. This code loads the Picker. But when I select an item from the Picker, I am getting a "Cannot read property 'type' of undefined error." I need urgent help to get this figured out. Please help.

Screenshot_20190315-145242_ypm

import React, { Component, Fragment }  from 'react';
import * as yup from 'yup'
import { Formik } from 'formik'
import { View, Button, Alert, Picker } from 'react-native';

export default class TestPickerFormik extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
          hasError: false,
          errorText: '',
          selectedBank:0,
        };
      }

    handleSubmit = () => {
          Alert.alert('Welcome');
      };

    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center' }}>
                <Formik
                    initialValues={{ bank: '' }}
                    onSubmit={this.handleSubmit}
                    validationSchema={yup.object().shape({
                        bank: yup
                            .string()
                            .required()
                    })}
                >
                    {({ values, handleChange, errors, setFieldTouched, touched, isValid, handleSubmit }) => (
                        <Fragment>
                            <View style={{ borderRadius: 3, borderWidth: 1 }}>

                                <Picker style={{ height: 40, width: 400 }}
                                    mode='dropdown'
                                    prompt={'Select bank'}
                                    itemStyle={{ backgroundColor: "grey" }}
                                    selectedValue={values.bank}
                                    onValueChange={(handleChange('bank'))}>
                                    <Picker.Item label='Select your bank' value={0} key={0} />
                                    <Picker.Item label='SBI' value={1} key={1} />
                                    <Picker.Item label='CITI' value={2} key={2} />
                                    <Picker.Item label='ICICI' value={3} key={3} />
                                </Picker>
                            </View>

                            <Button title='Submit' onPress={handleSubmit} />
                        </Fragment>
                    )}
                </Formik>
            </View>
        )
    }
}

I need urgent help to get this figured out. Please help.

Formik React-Native Workaround Question stale

Most helpful comment

I've been having a similar issue but with the <Switch /> component.

I think the root of this problem is that handleChange expects a String, I noticed the values in your picker were numbers so potentially the same issue

All 6 comments

I think there is an issue about picker behaviour and formik expectations:

onValueChange is called with two args instead of one for onChangeText. (https://facebook.github.io/react-native/docs/picker#onvaluechange)

Try something like:

                                <Picker style={{ height: 40, width: 400 }}
                                    mode='dropdown'
                                    prompt={'Select bank'}
                                    itemStyle={{ backgroundColor: "grey" }}
                                    selectedValue={Number(values.bank)}
                                    onValueChange={(...args) => handleChange('bank')(String(args[1]))}>
                                    <Picker.Item label='Select your bank' value={0} key={0} />
                                    <Picker.Item label='SBI' value={1} key={1} />
                                    <Picker.Item label='CITI' value={2} key={2} />
                                    <Picker.Item label='ICICI' value={3} key={3} />
                                </Picker>

Be careful if you use formik with validation onBlur because picker does not have onBlur prop.

onValueChange={(...args) => {
  handleChange('bank')(String(args[1]));
  setFieldTouched('bank', true);
}}>

I've been having a similar issue but with the <Switch /> component.

I think the root of this problem is that handleChange expects a String, I noticed the values in your picker were numbers so potentially the same issue

Included in a new umbrella issue. The workaround described above will work but we should make note of this in the docs. It would be good to perhaps make an “all inputs” React Native example.

Just stumbled upon same issue and I think using setFieldValue would be better practice since then you don't bother with type conversion e.g. string to int, boolean vice versa and also you keep desired data type on your form values. Though being all that said 1.5.x is perfectly handling types other than string so it would be nice to keep it that way.

We could try:
/component/AppInputs.js

export const AppPickerInput = ({ formikProps, formikKey, labelText, options=[] , ...rest}) => {
    return (
        <FieldWrapper
            formikKey={formikKey}
            labelText={labelText}
            formikProps={formikProps}>
            <View style={styles.PickerContainerStyle}>
                <Picker
                    itemStyle={{ color: 'red' }}
                    selectedValue={  value => {
                        formikProps.setFieldValue(formikKey, value)
                    } }
                    onValueChange={ value => {
                        formikProps.setFieldValue(formikKey, value)
                    }}

                    {...rest}
                    >
                    {
                       options.map( item => (
                            <Picker.Item label={item.label} value={item.value} />
                       ))
                    }
                </Picker>
            </View>
        </FieldWrapper>
    );
}

Then usage in another component after import

import { AppPickerInput } from './../path/components/AppInputs';
const MyApp = () => {
    const gender = [
        {label: 'Male', value: 'Male'},
        {label: 'Female', value: 'Female'}
    ];
return (
...
  <Formik
            initialValues={{ gender: "" }}
            onSubmit={ (val, actions) => {
            setTimeout( () => {
                    alert("Submitted! "+JSON.stringify(val));
                    }, 1000);
               } }
             validationSchema={validateEditPofile}
         >
      { formikProps => (
          ...
          <AppPickerInput 
                         formikProps={formikProps}
                         formikKey="gender"
                         selectedValue={formikProps.values.gender}
                         labelText="Gender"
                         options = {gender}
                  />
         ...
        )
       }
         </Formik>
...
);

}

Hope that helps. :-)

Was this page helpful?
0 / 5 - 0 ratings