How to save and display and image in react-native? - image

I have a question in react-native. Im using a module called "react-native-image-picker" to pick an image and display it on my app.
Now what i want is to store it somewhere (database, or local storage) and when i open again the app, the image that i choosed should be there. But i dont know what is the best option to do it.
I've already tryied to read some stuff like react-native-fs and fetch-blob but it doesnt help me, i guess.
What is the best option to do it?
Thank you.

First, renders view according to condition. For example if image is available then simply display the image else display TouchableOpacity which will help use to select pictures :
import React, { Component } from React;
import { View, TouchableOpacity, Text, Image } from 'react-native';
import ImagePicker from 'react-native-image-picker';
import AsyncStorage from '#react-native-community/async-storage';
class App extends Component {
constructor(props) {
super(props);
this.state = {
isImageAvailable: false,
profilePic: null
}
}
componentDidMount = () => {
this.getImage();
}
getImage = async () => {
const profilePic = await AsyncStorage.getItem("profilePic");
if (profilePic) {
this.setState({
isImageAvailable: true,
profilePic: JSON.parse(profilePic)
});
}
}
selectProfilePic = () => {
const options = {
title: 'Select Avatar',
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
const source = { uri: response.uri };
// You can also display the image using data:
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
AsyncStorage.setItem("profilePic", JSON.stringify(source));
this.setState({
profilePic: source,
isImageAvailable: true
});
}
});
}
render() {
return (
<View>
{
this.state.isImageAvailable && (
<Image source={this.state.profilePic} style={{ width: 200, height: 200 }} />
)
}
{
!this.state.isImageAvailable && (
<TouchableOpacity onPress={this.selectProfilePic}>
<Text>Choose Profile Pic</Text>
</TouchableOpacity>
)
}
</View>
)
}
}
Hope it will help you.

You can use realmdb as an aternative to Asyncstorage.

Related

How do I render an image using map function?

I've tried do render the image from URL but I have no success. If write the URI ok, but if I write item.show.image.original.replace ('http:', 'https:') to get the image no success.
The problem is thereĀ“s no error but not rendering.
The others values I've had success with.
import React, { Component } from "react";
import { Text, View, Image } from "react-native";
let termo = 'batman';
const API = 'http://api.tvmaze.com/search/shows?q='+termo;
export default class mapFunction extends Component {
constructor(props) {
super(props);
this.state = {
array: [], };
}
componentDidMount() {
fetch(API)
.then(response => response.json())
.then(data => this.setState({ array: data}));
}
list = () => {
return this.state.array.map(item => {
return (
<View style={{marginLeft: 10}}>
<Text>{item.score}</Text>
<Text>{item.show.name}</Text>
<Text>{item.show.type}</Text>
<Text>{item.show.language}</Text>
<Text>{item.show.summary} </Text>
<Image source={{uri:'https://static.tvmaze.com/uploads/images/original_untouched/6/16463.jpg'}}
style={{width:90, height:150}} />
</View>
);
});
};
render() {
return <View>{this.list()}
</View>;
}
}
Just change render function as below:
render() {
return (
<View>{this.list()}</View>
);
}

How to show Timeout for 25000 ms if API does not give data using redux?

I am new to react and redux. I have implemented API fetching using redux but not sure where should i put code for Timeout if API does not give gives data for particular time. everything is working fine I am getting data too..only thing i stuck is how to show timeout. Is there any way to do that? Thanks in advance :)
reducer.js
export const GET_REPOS = 'my-awesome-app/repos/LOAD';
export const GET_REPOS_SUCCESS = 'my-awesome-app/repos/LOAD_SUCCESS';
export const GET_REPOS_FAIL = 'my-awesome-app/repos/LOAD_FAIL';
const initialState = {
repos: [],
loading: false,
error: null
};
export default function reducer(state = initialState , action) {
switch (action.type) {
case GET_REPOS:
return { ...state, loading: true };
case GET_REPOS_SUCCESS:
return { ...state, loading: false, repos: action.payload.data };
case GET_REPOS_FAIL:
return {
...state,
loading: false,
error: 'Error while fetching repositories',
};
default:
return state;
}
}
export function listRepos(photos) {
return {
type: GET_REPOS,
payload: {
request: {
url: `photos/`
}
}
};
}
export function listThumb(albumId) {
return {
type: GET_REPOS,
payload: {
request: {
url: `photos?albumId=${albumId}`
}
}
};
}
home.js
import React, { Component } from 'react';
import { ActivityIndicator } from 'react-native-paper';
import { View, Text, FlatList, StyleSheet, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';
import styles from '../HomeComponent/style';
import { Ionicons } from '#expo/vector-icons';
import { listRepos } from '../../../reducer';
import ErrorAlert from '../../common/ErrorAlertComponent/errorAlert';
class Home extends Component {
componentDidMount() {
this.props.listRepos('');
}
FlatListItemSeparator = () => (
<View style={styles.flatListItemSeparator} />
)
renderItem = ({ item }) => (
<View style={styles.listRowContainer}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('ThumbnailViewScreen', {
albumID: item.id,
})} style={styles.listRow}>
<View style={styles.listTextNavVIew}>
<Text style={styles.albumTitle}> {item.title} </Text>
<Ionicons name='md-arrow-dropright' style={styles.detailArrow} />
</View>
</TouchableOpacity>
</View>
);
render() {
const { error, loading, products } = this.props;
if (error) {
return <ErrorAlert />;
}
if (loading) {
return (
<View style={{ flex: 1, paddingTop: 30 }}>
<ActivityIndicator animating={true} size='large' />
</View>
);
}
const { repos } = this.props;
return (
<View style={styles.MainContainer} >
<FlatList
styles={styles.container}
data={repos}
renderItem={this.renderItem}
ItemSeparatorComponent={this.FlatListItemSeparator}
/>
</View>
);
}
}
const mapStateToProps = state => {
let storedRepositories = state.repos.map(repo => ({ key: repo.id.toString(), ...repo }));
return {
repos: storedRepositories,
loading: state.loading,
error: state.error
};
};
const mapDispatchToProps = {
listRepos
};
export default connect(mapStateToProps, mapDispatchToProps)(Home);
Firstly you should create entry point for your axios. For example:
import axios from 'axios/index';
const api = axios.create({
baseURL: 'site.com',
timeout: 25000,
});
export default api;
And import it where you do api calls:
import api from 'yourDirectory';
And use this entry point:
api.get(url)
If request time is too long axios throws timeout error after 25000ms

How to upload a base64 image to S3 with amplify, react native application

Looking for a simple example of how to upload a base64 image to aws S3 using amplify.
Assuming you configured Amplify Storage and set the permissions to public, here is a code example that uses Storage from Amplify to upload images to S3 bucket. The images are fetched from the local device using ImagePicker from Expo.
import React from 'react';
import {
StyleSheet,
ScrollView,
Image,
Dimensions } from 'react-native'
import { ImagePicker, Permissions } from 'expo'
import { Icon } from 'native-base'
import Amplify from '#aws-amplify/core'
import Storage from '#aws-amplify/storage'
import config from './aws-exports'
class App extends React.Component {
state = {
image: null,
}
// fetch a single image from user's device and save it to S3
useLibraryHandler = async () => {
await this.askPermissionsAsync()
let result = await ImagePicker.launchImageLibraryAsync(
{
allowsEditing: false,
//aspect: [4, 3],
}
)
console.log(result);
if (!result.cancelled) {
this.setState({ image: result.uri })
this.uploadImage(this.state.image)
}
}
// add a single image to S3
uploadImage = async uri => {
const response = await fetch(uri)
const blob = await response.blob() // format the data for images
const folder = 'images'
const fileName = 'flower.jpeg'
await Storage.put(folder + '/' + fileName, blob, {
contentType: 'image/jpeg',
level: 'public'
}).then(data => console.log(data))
.catch(err => console.log(err))
}
render() {
let { image } = this.state
let {height, width} = Dimensions.get('window')
return (
<ScrollView style={{flex: 1}} contentContainerStyle={styles.container}>
<Icon
name='md-add-circle'
style={styles.buttonStyle}
onPress={this.useLibraryHandler}
/>
{/*
true && expression always evaluates to expression,
and false && expression always evaluates to false
*/}
{image &&
<Image source={{ uri: image }} style={{ width: width, height: height/2 }} />
}
</ScrollView>
);
}
}
The name of the image is hardcoded which is not good. But this is a very good start nonetheless.
This is a simple method for uploading multiple images. It should work for single image too.
import {Storage} from "aws-amplify";
UploadPhotos(SelectedImages) {
SelectedImages.forEach(async (element) => {
let name = element.filename;
let access = { level: "protected", contentType: "image/jpeg" };
let imageData = await fetch(element.uri);
let blobData = await imageData.blob();
try {
Storage.put(name, blobData, access);
} catch (err) {
console.log("UploadPhotos error: ", err);
}
});
}

Image fails to render after successful fetch in React native

I'm attempting to render an image that is the result of a successful fetch.
It seems fairly simple and everything works, except the picture fails to render.
In my constructor:
constructor(props) {
super(props);
const deliveryManPic = Config.images.deliveryManPic;
this.state = {
callModal: false,
beepModal: false,
pictureForBackground: null,
finished: deliveryManPic,
secondPic: null,
};
this.batteryLevelIndicator = '';
this.pictureUrl = 'someURL';
}
In my ComponentWillMount:
componentWillMount() {
const urlForPicture = this.pictureUrl;
apiService.getPicture(urlForPicture, (res) => {
if (res !== null) {
// console.log('here is your response', res);
this.setState({ pictureForBackground: res, });
} else {
loggingService.debug('theres been a problem');
}
});
}
Finally, inside my render method:
<View style={styles.deliveryGuyView}>
<Image
resizeMode="cover"
style={styles.policeCarIcon}
defaultSource={{ uri: this.state.finished }}
source={{ uri: this.state.pictureForBackground }}
onLoadEnd={() => {
console.log('pic has finished loading');
}}
/>
</View>
I don't see any yellow messages or errors in the console.log, but I don't see the picture that was successfully fetched. What could be the reason the picture fails to render?
I forgot to add the height and width inside the PoliceCarIcon styles object.

Change Image when clicked and again change to previous image when again clicked in React Native

I need to change the image when clicked on the image and again if the image is clicked i need to return to the previous state when again clicked on the image in react native my code is:
constructor (props) {
super(props);
this.state = {
toggleCollapse: false,
selectedUnit: null,
uri: require('../resources/icons/circle.png')
};
_onPress = () => {
this.props.onPressItem(this.props.item, this.props.index);
this._renderLessons(this.props.item, this.props.index);
this.setState({
toggleCollapse: !this.state.toggleCollapse,
uri: require('../resources/loader.gif')
});
}
Here how I do it:
images = {
'first_image': require('../resources/icons/circle.png'),
'second_image': require('../resources/loader.gif'),
};
class Example extends Component {
constructor (props) {
super(props);
this.state = {
toggleCollapse: false,
selectedUnit: null,
};
}
_onPress = () => {
.....
this.setState({
toggleCollapse: !this.state.toggleCollapse
});
}
render() {
return (
....
<Image source={this.state.toggleCollapse ? images.first_image : images.second_image} />
....
)
}
}
Have two states that switch values
constructor (props) {
super(props);
this.state = {
toggleCollapse: false,
selectedUnit: null,
next = require('../resources/icons/circle.png'),
uri: require('../resources/icons/circle.png') ,
temp_store: ''
};
_onPress = () => {
this.props.onPressItem(this.props.item, this.props.index);
this._renderLessons(this.props.item, this.props.index);
this.setState({
toggleCollapse: !this.state.toggleCollapse,
temp_store: this.state.uri,
uri: this.state.next,
next: this.state.temp_store
});
}
Basically, store the current uri in a temporary state, change uri to the next state and then make the previous uri(inside temp_store) the next state.

Resources