DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Resolving Expo Multi Select Photos with React Hooks
Mauricio Reatto Duarte for Expo Lovers β™₯️

Posted on • Originally published at atalkwith.dev on

Resolving Expo Multi Select Photos with React Hooks

Created: Nov 26, 2019 10:07 PM Tags: Expo, React Native, javascript

Introduction

Do you know the Expo project? Expo is a framework and a platform for universal React applications. It is a set of tools and services built around React Native and native platforms that help you develop, build, deploy, and quickly iterate on iOS, Android, and web apps from the same JavaScript/TypeScript codebase.

Workflows

The two approaches to building applications with Expo tools are called the β€œmanaged” and β€œbare” workflows.

  • With the managed workflow you only write JavaScript / TypeScript and Expo tools and services take care of the rest for you.
  • In the bare workflow, you have full control over every aspect of the native project, and Expo tools can’t help quite as much.

We won’t tell about the bare workflow at this moment, only a problem with so many people using Expo SDK 33 or later.

Expo ImagePicker - launchImageLibraryAsync

There is the ImagePicker on the API for display the system UI for choosing an image or video from the phone’s library, but there isn’t a way to allow multiple selections of images, as you can see here. There are some feature requests here:

The solution with React Hooks

In React Native, you can use the Camera Roll API to get media from the phone’s library, then why not build a hook for that? :]

import { useCallback, useState } from 'react';
import { CameraRoll } from 'react-native';

export default function useCameraRoll({
  first = 40,
  assetType = 'Photos',
  groupTypes = 'All',
}) {
  const [photos, setPhotos] = useState([]);
  const [after, setAfter] = useState(null);
  const [hasNextPage, setHasNextPage] = useState(true);

  const getPhotos = useCallback(async () => {
    if (!hasNextPage) return;

    const { edges, page_info: pageInfo } = await CameraRoll.getPhotos({
      first,
      assetType,
      groupTypes,
      ...(after && { after }),
    });

    if (after === pageInfo.end_cursor) return;

    const images = edges.map(i => i.node).map(i => i.image);

    setPhotos([...photos, ...images]);
    setAfter(pageInfo.end_cursor);
    setHasNextPage(pageInfo.has_next_page);
  }, [after, hasNextPage, photos]);

  return [photos, getPhotos];
}

After that, you simply use it like this:

// path to your hooks
import { useCameraRoll } from 'shared/hooks';

// ...

function SomeComponent() {
    const [photos, getPhotos] = useCameraRoll({ first: 80 });

    // ...
}

You can use getPhotos in a FlatList onEndReached props , for instance. Problem solved :]

References

Top comments (6)

Collapse
 
jiahong96 profile image
Loo Cheah Hong

requires eject (bare workflow) to use this solution? as seen in github.com/react-native-community/...

Collapse
 
mauriciord profile image
Mauricio Reatto Duarte

hey,
This post is deprecated, so I'll update asap! thanks for reply

Collapse
 
mhhonline profile image
Mohammed Hassan

Greetings,

any update to this subject. I am interested in using the workaround to upload images and videos as well!

Regards,

Thread Thread
 
mauriciord profile image
Mauricio Reatto Duarte

Yeah, I'm planning to update it. Stay alert! : ]

Thread Thread
 
mhhonline profile image
Mohammed Hassan

Thanks for your support. I am waiting for you!

Regards,

Thread Thread
 
mhhonline profile image
Mohammed Hassan

Hi MaurΓ­cio R Duarte,

any update? thanks in advance

Classic DEV Post from 2020:

js visualized

πŸš€βš™οΈ JavaScript Visualized: the JavaScript Engine

As JavaScript devs, we usually don't have to deal with compilers ourselves. However, it's definitely good to know the basics of the JavaScript engine and see how it handles our human-friendly JS code, and turns it into something machines understand! πŸ₯³

Happy coding!