简体   繁体   中英

Expo React Native, How to pick default local images or user image obtained from expo image picker

I have a form that a user can select a default local image or an image from the user's photo library

Here is an expo snack use android the images can be found in the phone menu in photos

I want to save either the default local image or user's image to the form and to redux, currently able to save default images picked to form and redux.

This is what currently works. I have a component that gets a selected local image and returns an image path witch is a number. That local image gets saved in form and in redux. currently, the user can change the local image in the form.

ImgSelector Component:
    
    import React, { useState } from "react";
    import { List, Selector, View, SelectedImg } from "./styles";
    import { FlatList } from "react-native";
    import { defaultImages } from "../../data/defaultImages";

    const FlatlistItem = ({ image, setImg }) => {
    return (
       <Selector onPress={() => setImg(image)}>
         <View>
           <SelectedImg source={image} />
          </View>
       </Selector>
     );
    };

    const ImgSelector = ({ setImg }) => {
    const [selectedId, setSelectedId] = useState(null);
    const renderItem = ({ item }) => (
      <FlatlistItem setImg={setImg} image={item.image} />
    );

    return (
      <View>
        <FlatList
          horizontal
          data={defaultImages}
          renderItem={renderItem}
          keyExtractor={(item, index) => index.toString()}
          extraData={selectedId}
         />
       </View>
     );
   };

   export default ImgSelector;

Default local images are stored like this and the path is the index which is a number this part works fine.

export const defaultImages = [
    {
      id: “2”,
      image: require("../assets/images/singlepane.png"),
    }
 ]

I have an imagePicker component that asks for permissions and returns a uri string that looks like this:

file:/data/data/host.exp.exponent/cache/ExperienceData/%2540anonymous%252FExpoWcPro-a828b17b-dcd7-4a04-93ca-657c8e4e511d/ImagePicker/6106d73f-c886-457d-abe9-1f1232a0d398.jpg

My form component where images are picked and saved:

    import React, { useState } from "react";

    import { Image } from "react-native";

    const CounterForm = ({ navigation, ...props }) => {
    // This is current state for default images that works
    const [imgUrl, setImgUrl] = useState(props.imgUrl || defaultImage);

    const [userImgUri, setUserImgUri] = useState(null);

    // This gets the local image from a componnet
    const handleEditImg = (newImgUrl) => {
      setImgUrl(newImgUrl);
    };

    // This gets image uri from expo image picker
    const handelUserImg = (userUri) => {
      setUserImgUri(userUri);
    };

    // This sends data to a redux action to save
    const handleSubmit = () => {
      props.onFormSubmit({
        id: props.id,
        imgUrl,
      });
      setImgUrl(defaultImage);
    };

    return (
      <FormWrapper>
        <Row>
          <FormButton onPress={() => handleSubmit()}>
            <StyledText title="Save" color={COLORS.appBlue} />
          </FormButton>
        </Row>
        <TopContent>
          {/* I tried this to get user image and displays in form */}
          <Image
            source={{ uri: userImgUri }}
            style={{ width: 100, height: 100 }}
          />

          {/* This current implementation gets local images
          <Image
            source={imgUrl}
            style={{ width: 100, height: 100 }}
          /> */}

          {/* I tried this only gets local images
          {imgUrl ? (
            <Image source={imgUrl} style={{ width: 100, height: 100 }} />
          ) : (
            <Image
              source={{ uri: userImgUri }}
              style={{ width: 100, height: 100 }}
            />
          )} */}
        </TopContent>
        <Row>
          <ImagePicker getUserImg={handelUserImg} />
        </Row>
        <View>
          <ImgSelector setImg={handleEditImg} />
        </View>
      </FormWrapper>
    );
  };

  export default CounterForm;

if you use the last sdk version of Expo (40) and the right package expo-image-picker you need to follow this instructions.

First you need to ask for permissions:

const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
  alert('Sorry, we need camera roll permissions to make this work!');
}

And then call method to select image from library:

let result = await ImagePicker.launchImageLibraryAsync({
  mediaTypes: ImagePicker.MediaTypeOptions.All,
  allowsEditing: true,
  aspect: [4, 3],
  quality: 1,
});

So you got image uri by accessing result.uri , you need to save this value (eg in user store) and display it by selecting your store or default value if there is not stored value:

<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
  <Button title="Pick an image from camera roll" onPress={pickImage} />

  /** imgUrl = stored image uri, defaultImages[0].image = default image uri */
  <Image source={imgUrl ? { uri: imgUrl } : defaultImages[0].image} />
</View>

I found the answer it's updated in expo snack

import React, { useState } from "react";
import { List, Selector, View, SelectedImg } from "./styles";
import { FlatList } from "react-native";
import { defaultImages } from "../data";


const FlatlistItem = ({ image, setImg }) => {
  return (
    <Selector onPress={() => setImg(image)}>
      <View>
        <SelectedImg source={{uri: image}} />
      </View>
    </Selector>
  );
};

const ImgSelector = ({ setImg }) => {
  const [selectedId, setSelectedId] = useState(null);
  const renderItem = ({ item }) => {
    return (
    <FlatlistItem setImg={setImg} image={item} />
  )
  }

  return (
    <View>
      <FlatList
        horizontal
        data={defaultImages}
        renderItem={renderItem}
        keyExtractor={(item, index) => index.toString()}
        extraData={selectedId}
      />
    </View>
  );
};

export default ImgSelector;

Form

import React, { useState } from "react";
import {Asset} from 'expo-asset';
import StyledText from "../UiComponents/StyledText";
import { TouchableWithoutFeedback, Keyboard } from "react-native";
import {
  FormWrapper,
  TextInputWrapper,
  TopContent,
  NumberWrapper,
  Row,
  FormButton,
  View,
} from "./styles";
import StyledInput from "../UiComponents/StyledInput";
const defaultImage = Asset.fromModule(require('../assets/komloy.jpg')).uri
import WindowSelector from "../ImgSelector";
import StyledButton from "../UiComponents/StyledButton";
import ImagePicker from "../components/imagePicker";
import { Image } from "react-native";

const DismissKeyboard = ({ children }) => (
  <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
    {children}
  </TouchableWithoutFeedback>
);

const CounterForm = ({ navigation, ...props }) => {
  const [imgUrl, setImgUrl] = useState(props.imgUrl || defaultImage);
  
  const handleEditImg = (newImgUrl) => {
    setImgUrl(newImgUrl);
  };

  const handelUserImg = (userUri) => {
    setImgUrl(userUri);
  };

  const handleSubmit = () => {
    props.onFormSubmit({
      id: props.id,
      imgUrl
    });
    setImgUrl(defaultImage);
  };

  return (
    <DismissKeyboard>
      <FormWrapper>
        <TopContent>
         <Image
            source={{uri: imgUrl}}
            style={{ width: 100, height: 100 }}
          />
        </TopContent>
        <Row>
          <StyledText title="Select a image" />
          <ImagePicker getUserImg={handelUserImg} />
        </Row>
        <View>
          <WindowSelector setImg={handleEditImg} />
        </View>
      </FormWrapper>
    </DismissKeyboard>
  );
};

export default CounterForm;

Data

 import {Asset} from 'expo-asset';

const imageURI = Asset.fromModule(require('./assets/islands.jpg')).uri
const imageURI2 = Asset.fromModule(require('./assets/maeYai.jpg')).uri

export const defaultImages = [
 imageURI, imageURI2
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM