Local storage can be implemented in a React Native application so that application data can be persisted when it is closed and reopened
React Native provides AsyncStorage
to implement data storage
Example provided uses Storage
component of react-native-storage
package, which is awrapper over AsyncStorage
, to store the index of a selected tab
// imports for implementing local storage
import Storage from 'react-native-storage';
import AsyncStorage from '@react-native-community/async-storage';
// tabview is specific to provided example
import ScrollableTabView, { ScrollableTabBar } from 'react-native-scrollable-tab-view';
Declare storage, preferably as a global variable
storageBackend
is set to AsyncStorage
enabling the data to persist
Function declared in sync
is to be called when data for corresponding key (identifiers) is not found in storage
const storage = new Storage({
// maximum capacity of key-value pairs
// size: 1000,
// Use AsyncStorage for React Native apps
// If storageBackend is not set, data is lost after reload
storageBackend: AsyncStorage,
// default expire time in milliseconds, null to not expire
// defaultExpires: 1000 * 3600 * 24,
// cache data in the memory
enableCache: true,
// if data is not found in storage or expired data is found,
// the corresponding sync method is invoked to get data
sync: {
// name of sync method should be same as 'key' of data stored
// this method can include network call
tabIndex() {
console.log('sync call');
return 0;
}
}
});
Use storage.save()
method to store data for a key
, where data can be an object
storage.save({
key: 'tabIndex', // Do not use underscore("_") in key
data: index.i,
// expire time in milliseconds, null to not expire
// expires: 1000 * 3600
});
Use storage.load()
method to get data for a key
storage
.load({
key: 'tabIndex',
// autoSync (default: true) - if data is not found or has expired,
// then corresponding sync method is invoked
// autoSync: true,
// if syncInBackground is false then expired data is not returned while syncing
// syncInBackground: false,
})
.then(index => { this.setState({tabIndex:index})})
.catch(err => {
console.error(err);
if(!this.state.tabIndex)
this.setState({tabIndex:0}); //precautionary
}
)
Check React Native Installation for installation related info
Use react-native init
command to create a new React Native project (here named LocalStorageApp)
react-native init LocalStorageApp
This creates a directory named LocalStorageApp and initializes it as a react native application directory
This can be skipped in case an existing react native project is being integrated into
Since this example uses ScrollableTabView component, react-native-scrollable-tab-view
package has to be added
Go to project directory (here LocalStorageApp)
cd LocalStorageApp
Add react-native-storage
, @react-native-community/async-storage
and react-native-scrollable-tab-view
to project using yarn
yarn add react-native-storage @react-native-community/async-storage react-native-scrollable-tab-view
or using npm
npm install react-native-storage @react-native-community/async-storage react-native-scrollable-tab-view --save
After yarn add
command, run pod install
command in ios folder inside project directory to install any required CocoaPods dependencies
cd ios && pod install && cd ..
In App.js a ScrollableTabView
is declared to show different tabs
Since storage methods are async, a progress indicator is shown till an initial value for tab index can be set
When app is opened first time, tabIndex()
method of sync
is called since storage doesn't contain value for key tabIndex
For subsequent restarts of the application, index is retrieved from storage
import React from 'react';
import { ActivityIndicator, StyleSheet, Text, View, Image } from 'react-native';
import ScrollableTabView, { ScrollableTabBar } from 'react-native-scrollable-tab-view';
import Storage from 'react-native-storage';
import AsyncStorage from '@react-native-community/async-storage';
const storage = new Storage({
storageBackend: AsyncStorage,
enableCache: true,
sync: {
tabIndex() {
return 0;
}
}
});
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
tabIndex: null,
};
}
componentDidMount() {
this.getIndexFromStorage();
}
async getIndexFromStorage() {
storage.load({key: 'tabIndex'})
.then(index => { this.setState({tabIndex:index})})
.catch(err => {
console.error(err);
if(!this.state.tabIndex)
this.setState({tabIndex:0}); //precautionary
}
)
};
tabChanged = (index) => {
// store tab index in storage
storage.save({
key: 'tabIndex',
data: index.i,
});
// setState is not called
this.state.tabIndex = index.i;
};
renderTabView(index) {
return (
<ScrollableTabView
style={{ marginTop: 20 }}
initialPage={index}
onChangeTab={this.tabChanged}
renderTabBar={() => <ScrollableTabBar />}
>
<View style={[styles.tab, {backgroundColor: 'orange'}]} tabLabel='Tab #1'><Text>Eat</Text></View>
<View style={[styles.tab, {backgroundColor: 'purple'}]} tabLabel='Tab #2'><Text>Sleep</Text></View>
<View style={[styles.tab, {backgroundColor: 'dodgerblue'}]} tabLabel='Tab #3'><Text>Change tab</Text></View>
<Image tabLabel='Tab #4' style={styles.image} source={{uri:"https://resourceplus.files.wordpress.com/2015/01/image.jpg"}} />
</ScrollableTabView>
)
}
render() {
const index = this.state.tabIndex;
// show progress indicator till an initial value is set for tabIndex
view = index !=null ? this.renderTabView(index) :
<View style={styles.container}>
<ActivityIndicator size="small" color="#00ff00" />
</View>
return (view)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
tab: {
alignItems: 'center',
justifyContent: 'center',
height: '100%',
},
image: {
resizeMode: 'stretch',
width: '100%',
height: '100%'
}
});
cd into project directory (here LocalStorageApp)
cd LocalStorageApp
Run metro server to serve js
react-native start
Go to project directory in another terminal tab
Enter following run command for Android:
react-native run-android
cd into project directory (here LocalStorageApp)
cd LocalStorageApp
Enter following command :
react-native run-ios
This might take some time
If the app shows error about metro server not configured (check Running an App in iOS), then run metro server in another tab:
react-native start
Reload the app
Re-run react-native run-ios
command if reloading doesn't work