Image Picker form in React Native using expo and Formik library

In React Native, there are many ways to implement an image picker, this article aims to show you how to use expo ImagePicker within a form using Formik.

Who is this article for?

Any person who is trying to create a form in React Native which has an image field. Please note, the module I used is part of the expo library, so expo needs to be setup for your project.

What will we make?

To display a use of these technologies, we will create a simple form with two fields, image and it’s title.

What is Formik?

This is Formiks intro as per their github:

Formik is a small library that helps you with the 3 most annoying parts:
- Getting values in and out of form state
- Validation and error messages
- Handling form submission
By colocating all of the above in one place, Formik will keep things organized — making testing, refactoring, and reasoning about your forms a breeze.

What does expo ImagePicker do?

As per documentation, the ImagePicker “Provides access to the system’s UI for selecting images and videos from the phone’s library or taking a photo with the camera.

If your react native project is already using expo, this is the way to go. Out of the box it gives you options to encode pictures, crop them, maintain aspect ratios, etc. Another reason to use this library is you don’t have to perform any extra “link” operations as required by other modules.

The Example:

This snack shows the example I am going to break down in the article below. This example also uses react-native-paper. This was done to use better looking out of the box components, but it is not required.

Setup

Again the assumption is expo is already setup, this guide will not cover how to setup expo. You can always install the expo module to get the modules anyway.

The installation is pretty simple for Formik:

npm install formik — save
# or
yarn add formik

Essentially the same steps are required to install react-native-paper:

npm install react-native-paper — save
# or
yarn add react-native-paper

Detailed guidelines can be found under their getting started guide;

Imports

Add the following imports to your form component or page, details are explained in the comments:

// ImagePicker component is needed to do the actual import
import { ImagePicker } from ‘expo’;
// Formik imported to keep track of the forms state
import { Formik } from ‘formik’;
// Optional UI components, out of the box, good looking components
import { Button, TextInput } from ‘react-native-paper’;
// Optional UI components, used to show/style the output
import { Alert, Keyboard, Image, View, StyleSheet } from ‘react-native’;

Using Formik:

After you have imported Formik, the parent component of your form is Formik. It can be rendered as shown below:

<Formik initialValues={initialValues} onSubmit={this.onSubmit.bind(this)}>
{(props) => (<Render form components>)}
</Formik>

Formik has other attributes that can be passed in, but those are not covered in this article.

Formik Props:

initalValues are the initial values passed in for your form inputs. All values must be initialized to avoid error conditions.

onSubmit is a submission handler, by default it has params values and FormikBag. We only cover values in this article. These are the values that are submitted when the handle submission is called.

Formik follows a Render Props design pattern, the render function for form inputs can be passed in as a prop, or nested as shown in the example above. In my snack example, you will notice I destructured the props to pick the arguments I want so instead of doing (props), I did ({ handleChange, handleSubmit, values }). There are many other props available, use as per need. handleChange and handleSubmit are handlers available by Formik to keep track of your state, and also a clean way to handle final submission. All input fields in react by default want a change handler, buttons want on press handlers etc, so these are very useful.

Using the text input:

In my example, I used an input field to get a “title” from the user, this was done by rendering a component using:

<TextInput
onChangeText={handleChange(‘title’)}
value={values.title}
label=”Title”
placeholder=”e.g My Awesome Selfie”/>

handleChange and values are given to us from Formik. handleChange is a general input change event handler. By passing in the key, it will return a handler that updates values[key] in the forms state.

Using the Image picker:

ImagePicker has a method called launchImageLibraryAsync(options) displays the systems UI to select an image/video etc. The function below, accepts an input handler, where the input is the URI of the image, it launches the Image Picker, and then passes the URI(if any) to the handler. The options passed in allow you to edit an image before selecting it, the image aspect ratio is also maintained.

async _pickImage (handleChange) {
let result = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
aspect: [4, 3]
})
console.log(result)
if (!result.cancelled) {
handleChange(result.uri)
}
}

In the Formik render method, we can add the following Button to call the function above:

<Button
icon=”add-a-photo”
mode=”contained”
style={styles.button}
onPress={() => {this._pickImage(handleChange(‘image’))}}>
Pick an image from camera roll
</Button>

This is a react-native-paper component. The only key thing here is the function passed in onPress. Using closures, we are able to pass in Formiks change handler, that will accept the image URI; this change handler is used by the function _pickImage.

The selected image can be rendered using the following line:

{values.image && values.image.length > 0 ?
<Image source={{ uri: values.image }} style={{ width: 200, height: 200 }} /> : null}

Finally, submission is done using this Button component:

<Button onPress={handleSubmit} style={styles.button}>Submit</Button>

onPress calls an event handler that is called when the button is pressed. handleSubmit is a handler that is given to us by Formik. This will call the function passed in the initial Formik component, in our case onSubmit which will have the values that were tracked by this form.

Hopefully this gives an idea on how to use Formik and an image picker.

Let me know if you have any questions, and feel free to give me any remarks on my first medium article!

References:

- https://jaredpalmer.com/formik/docs/api/formik
- https://docs.expo.io/versions/latest/sdk/imagepicker
- https://callstack.github.io/react-native-paper
- https://snack.expo.io/@ferrannp/react-native-x-formik
- https://snack.expo.io/@quinlanj/imagepicker-from-from-camera-roll