Wednesday, March 15, 2023
HomeReactConstructing offline React Native apps with AsyncStorage by Aman Mittal

Constructing offline React Native apps with AsyncStorage by Aman Mittal


Constructing offline React Native apps with AsyncStorage

Printed on Aug 18, 2019

34 min learn

cover

As builders, we love exploring ideas and mechanisms whereas working with a brand new framework. React Native as a cross-platform growth framework has come fairly far by way of a mature framework since I began enjoying round with it after which utilizing it for its objective. Understanding the basics when studying it’s one thing very useful, and I contemplate, necessary.

Thus, making use of fundamental fundamentals of React Native data, on this tutorial, I’m going to stroll you thru the best way to construct a todo record software utilizing an offline storage performance. This storage performance is offered by a local module in React Native, known as AsyncStorage.

Within the journey of constructing this software, you’ll use a UI element library generally known as Native Base, which is without doubt one of the hottest libraries to construct consumer interfaces amongst React Native builders. Out of the field, this library accelerates the event course of by offering pre-defined UI parts that may both be used as they’re out there or customise them in response to our wants.

What are we constructing?

🔗

The end result from following this tutorial goes to be an entire React Native software that works with realtime offline knowledge from the storage of the gadget.

Desk of Contents

🔗

  • Conditions
  • Create an Expo app
  • Exploring AsyncStorage
  • Using AsyncStorage API
  • Including Navigation
  • Making a Floating Motion Button (FAB)
  • Navigating between Two Screens
  • Customise the Header Part
  • Rendering an inventory of things utilizing FlatList
  • Studying Information utilizing AsyncStorage API
  • Including a Todolist Merchandise
  • Deleting a Todolist Merchandise
  • Mark an Merchandise Test or Uncheck on completion
  • Passing Information between completely different screens utilizing the navigation
  • Show every todo record merchandise
  • Bonus Part: Including a Section
  • Conclusion

Conditions

🔗

To observe this tutorial, please be sure you have the next put in in your native growth atmosphere and have entry to the providers talked about beneath:

  • Node.js (>=8.x.x) with npm/yarn put in.
  • expo-cli (>=3.0.4), beforehand generally known as create-react-native-app.

It will likely be greatest in case you use the identical actual variations or larger of every utility instrument described above. To run and check the React Native software, all you want is an Expo consumer put in both in your gadget or an iOS simulator or an Android emulator. Please notice that, all through this tutorial, I will probably be utilizing an iOS simulator to reveal the appliance.

Create an Expo app

🔗

To get began, all you require is to generate a brand new Expo venture. This could possibly be achieved by opening a terminal window, navigating to an acceptable location the place you develop initiatives and operating the next instructions within the order they’re described.

expo init offline-todolist-app

cd offline-todolist-app

yarn add react-navigation native-base

expo-font@5.0.1 lodash.values uuid

The final command, as described within the above snippet installs 5 dependencies that the appliance goes to make use of. yarn is at present getting used because the package deal supervisor. You too can use npm as an alternative of yarn. Using every dependency will probably be made clear as all through this tutorial as they’re used. If that is your first time constructing a React Native software, attempt to not get overwhelmed by them.

Exploring AsyncStorage

🔗

AsyncStorage is a straightforward, asynchronous key-value pair utilized in React Native functions. It’s used for quite a lot of eventualities however primarily to retailer knowledge when your app isn’t utilizing any cloud providers, otherwise you need to implement some options in your app that require knowledge storage.

It operates globally in a React Native and comes with its personal limitations. As a React Native developer, you need to know what these limitations. The primary limitation of an AsyncStorage API is that the dimensions of the database is ready to 6MB restrict. Additionally, AsyncStorage storage relies on SQLite. Thus, you will need to preserve SQLite limitations in thoughts too. Additionally, it’s exhausting to retailer complicated and nested knowledge constructions in type of key-value pairs. Figuring out about these limitations, solely assist you to to go for the persistent resolution when growing a cell app.

In line with the React Native’s official documentation:

On iOS, AsyncStorage is backed by native code that shops small values in a serialized dictionary and bigger values in separate recordsdata. On Android, AsyncStorage will use both RocksDB or SQLite primarily based on what is obtainable.

Using AsyncStorage API

🔗

Earlier than you dive deep in constructing the Todolist app, on this part, allow us to construct a small app that saves a price to the AsyncStorage, fetches the worth from the storage within the client-side React Native app. It will assist you to the best way to write fundamental operations utilizing the storage API. Lastly, you’ll study the best way to clear the storage utterly.

Open App.js file and add the next snippet. Begin by importing the mandatory parts from React Native API. Crucial one right here is AsyncStorage. After that, outline a variable named STORAGE_KEY. This variable will probably be used to retailer and retrieve the saved knowledge utilizing the AsyncStorage API. Consider it as an identifier for the worth being saved or title of the important thing within the key-value pair. Since you’ll retailer just one worth in the meanwhile, there may be solely the requirement for one key.

1import React from 'react';

2import {

3 StyleSheet,

4 Textual content,

5 View,

6 TextInput,

7 AsyncStorage,

8 TouchableOpacity

9} from 'react-native';

10

11const STORAGE_KEY = '@save_name';

Subsequent, allow us to outline an preliminary state with two empty strings. They’ll be used to avoid wasting the worth of the consumer enter after which retrieve the worth to show it on the app display. After defining the preliminary state, there may be going to be a lifecycle methodology that’s going to load the info when the appliance begins for the primary time or the App element renders.

1class App extends React.Part {

2 state = {

3 textual content: '',

4 title: ''

5 };

6

7 componentDidMount() {

8 this.retrieveData();

9 }

10

11

12}

Within the above snippet, do notice that the App element is definitely a category element and never the default purposeful element that comes with boilerplate Expo app. Now, there are going to be three strategies that can assist to retailer the info, retrieve the info, and clear the app knowledge that’s saved. That is going to be achieved by creating three asynchronous strategies. Every of the strategies goes to make the most of the suitable API methodology from AsyncStorage API. Each methodology within the AsyncStorage API is a promise-based, therefore, allow us to use async/await syntax to observe good follow.

1retrieveData = async () => {

2 attempt {

3 const title = await AsyncStorage.getItem(STORAGE_KEY);

4

5 if (title !== null) {

6 this.setState({ title });

7 }

8 } catch (e) {

9 alert('Did not load title.');

10 }

11};

Within the above snippet, the title of the tactic implies what they’re going to do within the app. The retrieveData methodology is what fetches the info from the storage if it exists. It makes use of the identical identifier that you simply outlined beforehand, outdoors the category perform element. It utilises the parameter within the state object title. Later within the app, you’ll use this parameter to show its saved worth. Be aware that, there may be an if situation inside this methodology. This situation says that to fetch the info solely when there’s a worth for the title variable exists. This methodology additionally makes use of attempt/catch as they’re half and parcel of writing capabilities with fashionable async/await syntax. Lastly, this methodology is being invoked contained in the lifecycle methodology.

The subsequent perform goes to avoid wasting the info. Within the beneath snippet, you’ll discover that it makes use of a parameter title which on success, is the worth that’s saved. An alert message will probably be proven when the enter knowledge is saved.

1save = async title => {

2 attempt {

3 await AsyncStorage.setItem(STORAGE_KEY, title);

4 alert('Information efficiently saved!');

5 this.setState({ title });

6 } catch (e) {

7 alert('Failed to avoid wasting title.');

8 }

9};

The final methodology that you’re going to make the most of from the AsyncStorage API known as clear(). This deletes all the pieces that’s beforehand saved. It’s not really helpful to make use of this methodology immediately if you wish to delete solely a selected merchandise from the storage. For that, there are strategies like removeItem or multiRemove out there by the API. You’ll be able to learn extra about them within the official documentation right here or later when constructing the Todolist software.

1removeEverything = async () => {

2 attempt {

3 await AsyncStorage.clear();

4 alert('Storage efficiently cleared!');

5 } catch (e) {

6 alert('Did not clear the async storage.');

7 }

8};

This snippet will throw an Alert field on the gadget display when all the pieces is cleared from the storage.

The final two strategies are going for use to create a managed enter.

1onChangeText = textual content => this.setState({ textual content });

2

3onSubmitEditing = () => {

4 const onSave = this.save;

5 const { textual content } = this.state;

6

7 if (!textual content) return;

8

9 onSave(textual content);

10 this.setState({ textual content: '' });

11};

After that, add the code snippet for the render methodology, adopted by the types for every UI element. Lastly, don’t forget to export App element for it to run on the simulator or the actual gadget.

1render() {

2 const { textual content, title } = this.state

3 return (

4 <View fashion={types.container}>

5 <TextInput

6 fashion={types.enter}

7 worth={textual content}

8 placeholder='Kind your title, hit enter, and refresh'

9 onChangeText={this.onChangeText}

10 onSubmitEditing={this.onSubmitEditing}

11 />

12 <Textual content fashion={types.textual content}>Hiya {title}!</Textual content>

13 <TouchableOpacity onPress={this.removeEverything} fashion={types.button}>

14 <Textual content fashion={types.buttonText}>Clear Storage</Textual content>

15 </TouchableOpacity>

16 </View>

17 )

18 }

19}

20

21const types = StyleSheet.create({

22 container: {

23 flex: 1,

24 backgroundColor: '#fff',

25 alignItems: 'heart',

26 justifyContent: 'heart'

27 },

28 textual content: {

29 fontSize: 20,

30 padding: 10,

31 backgroundColor: '#00ADCF'

32 },

33 enter: {

34 padding: 15,

35 top: 50,

36 borderBottomWidth: 1,

37 borderBottomColor: '#333',

38 margin: 10

39 },

40 button: {

41 margin: 10,

42 padding: 10,

43 backgroundColor: '#FF851B'

44 },

45 buttonText: {

46 fontSize: 14,

47 coloration: '#fff'

48 }

49})

50

51export default App

Now to run the appliance, go to the terminal window and execute the command expo begin. After that, you will notice the next display on the simulator.

Since there is no such thing as a knowledge saved proper now, the textual content after the phrase Hiya is empty. Use the enter area to avoid wasting a string or a reputation or something after which press the enter key. You’re going to get the next output. No matter enter you entered, will probably be displayed subsequent to the phrase Hiya.

Even in case you refresh the Expo consumer, the worth saved doesn’t go away. Solely when urgent the button beneath Hiya assertion that claims Clear Storage is the way in which to delete the saved worth.

Refresh the Expo consumer after you clear the storage to get the next output.

This entire the part the place you discovered about the best way to make the most of AsyncStorage API to avoid wasting and fetch the info. From the subsequent part onwards, you can be constructing the Todolist software.

Organizing the appliance

🔗

Since a React Native software was already generated within the earlier step, you may proceed to make the most of that app by modifying all the pieces contained in the App.js file. Or create a brand new one if it serves you properly.

You’ve gotten already put in the mandatory npm modules. That is the time to begin using them with a view to construct the offline todo record app. Earlier than starting with the event of the app, create the next folders and recordsdata inside them. It will give a construction to handle the app later or if you wish to prolong by including new options to it.

From the construction, discover that there are three new folders being created. This construction is the separation of considerations between the completely different side of a cell app. Equivalent to recordsdata or configuration associated to navigation must be separated from the screens. The above construction can be a typical sample that many React Native builders have began to observe of their work.

Including Navigation

🔗

Contained in the navigation folder, there may be an index.js file that’s going to carry all of the configuration there may be to be outlined. The rationale react-navigation module is used is to create a stack navigator that enables the consumer to go to the 2 screens the next software has. The navigation mode goes to be modal. Sure, you may make the most of pre-defined navigation modes or animation patterns.

Allow us to begin by importing the mandatory parts contained in the index.js file.

1import React from 'react';

2import { createStackNavigator, createAppContainer } from 'react-navigation';

3import HomeScreen from '../screens/HomeScreen';

4import AddTaskScreen from '../screens/AddTaskScreen';

From the above snippet, discover that the createStackNavigator is a perform that returns a React element. It takes a route configuration object. The createAppContainer is chargeable for linking the present React Native app whereas sustaining the navigation state from the top-level element. The highest-level element in your app is App.

With the assistance of createAppContainer, you’ll create a supplier and wrap the App element inside it. It will profit the whole software as each display or element outlined goes to have a navigation state. You’ll study a few of the many advantages offered by the navigation state later.

Lastly, within the above snippet, there are going to be a display element. These display parts are going to carry the enterprise logic essential to run the todo record app. You’ll be able to consider them as containers.

Proper now, the route configuration object goes to be as the next snippet.

1const StackNav = createStackNavigator(

2 {

3 Residence: {

4 display: HomeScreen

5 },

6 AddTask: {

7 display: AddTaskScreen

8 }

9 },

10 {

11 mode: 'modal'

12 }

13);

The mode is necessary to specify right here. It defines the fashion for rendering the subsequent display element. Within the above case, it’s AddTask display. In an iOS or Android app, the default transition is all the time a card. You’re altering this default transition by specifying the mode property and setting its worth to modal.

The modal sample Make the screens slide in from the underside, which is a typical iOS sample. Solely works on iOS however has no impact on Android.

Lastly, you need to export the app container that makes use of the StackNav. Right here is the code for that.

1const RootNavigator = createAppContainer(StackNav);

2

3export default RootNavigator;

Now, open App.js file and add the next content material.

1import React from 'react';

2import RootNavigator from './navigation';

3

4export default perform App() {

5 return <RootNavigator />;

6}

Earlier than operating the app, be sure there’s a mock element to render contained in the recordsdata HomeScreen.js and AddTaskScreen.js. In any other case, it should throw an error. You’ll be able to add the dummy element for now.

1

2import React, { Part } from 'react';

3import { Textual content, View } from 'react-native';

4

5export class HomeScreen extends Part {

6 render() {

7 return (

8 <View>

9 <Textual content> Offline Todolist App</Textual content>

10 </View>

11 );

12 }

13}

14

15export default HomeScreen;

16

17

18import React, { Part } from 'react';

19import { Textual content, View } from 'react-native';

20

21export class AddTaskScreen extends Part {

22 render() {

23 return (

24 <View>

25 <Textual content>Add Job Display</Textual content>

26 </View>

27 );

28 }

29}

30

31export default AddTaskScreen;

Now run the app utilizing expo begin command, and you’ll get the next consequence.

This completes the navigation part.

Create a Floating button

🔗

Contained in the parts/FloatingButton.js file, you’ll create a floating motion button or in cell growth, generally generally known as FABs. These sort of buttons are sometimes distinguished by a circled icon floating above the UI in a hard and fast place. In case you are an Android consumer or have seen a cell app following any materials design specification, you might need seen them.

Within the present app, this FloatingButton goes to be chargeable for navigating from the HomeScreen to the AddTaskScreen. Since it’ll be a presentation element, it is best to outline it as a purposeful element that accepts just one prop. This prop actionOnPress goes to be a technique outlined contained in the HomeScreen.js file that can comprise the logic of navigating between the 2 screens later.

One necessary factor to note within the snippet beneath is that the element library native-base is getting used to create the FAB button. It saves period of time and features of code to create and elegance a element like beneath.

1import React from 'react';

2import { StyleSheet } from 'react-native';

3import { Icon, Fab } from 'native-base';

4

5const FloatingButton = ({ actionOnPress }) => (

6 <Fab

7 route="up"

8 fashion={types.button}

9 place="bottomRight"

10 onPress={actionOnPress}

11 >

12 <Icon title="ios-add" />

13 </Fab>

14);

15

16const types = StyleSheet.create({

17 button: {

18 backgroundColor: '#5859f2'

19 }

20});

21

22export default FloatingButton;

Navigating Between Two Screens

🔗

Upon getting outlined it, go to the file HomeScreen.js and the next snippet of code.

1import React, { Part } from 'react';

2import { View, Textual content, StyleSheet } from 'react-native';

3import { AppLoading } from 'expo';

4import * as Font from 'expo-font';

5import FloatingButton from '../parts/FloatingButton';

6

7export class HomeScreen extends Part {

8 state = {

9 isDataReady: false

10 };

11 componentDidMount = () => {

12 this.loadFonts();

13 };

14

15 loadFonts = async () => {

16 attempt {

17 await Font.loadAsync({

18 Roboto: require('../node_modules/native-base/Fonts/Roboto.ttf'),

19 Roboto_medium: require('../node_modules/native-base/Fonts/Roboto_medium.ttf'),

20 Ionicons: require('../node_modules/native-base/Fonts/Ionicons.ttf')

21 });

22 this.setState({ isDataReady: true });

23 } catch (err) {

24 alert('Software Error. Can't load fonts.');

25 }

26 };

27

28 onPressFab = () => {

29 this.props.navigation.navigate('AddTask');

30 };

31

32 render() {

33 const { isDataReady } = this.state;

34

35 if (!isDataReady) {

36 return <AppLoading />;

37 }

38 return (

39 <View fashion={types.container}>

40 <Textual content>Residence Display</Textual content>

41 <FloatingButton actionOnPress={this.onPressFab} />

42 </View>

43 );

44 }

45}

46

47const types = StyleSheet.create({

48 container: {

49 flex: 1

50 }

51});

52

53export default HomeScreen;

Within the above snippet, the primary and necessary factor to note is the loadFonts methodology. This asynchronous methodology is a requirement to make Native Base UI library to work in any React Native, and Expo generated software. NativeBase use some customized fonts which are loaded utilizing Font.loadAsync perform. This perform is offered by the expo module expo-font which lets you use any fonts or icons in React Native parts.

The AppLoading methodology is a React element that tells Expo to maintain the app loading display seen till Font.loadAsync() the tactic has run efficiently. Basically, this a helpful methodology to make the most of when your app is utilizing customized fonts, logos, icons, and so forth. Within the present software, you’ll make the most of this React element once more when fetching knowledge from AsyncStorage API (that you will notice in motion later on this tutorial). The AppLoading will solely cease operating when the boolean worth for the state variable isDataReady is ready to true. This boolean worth is barely set to true when Font.loadAsync() has completed operating.

As soon as the appliance has loaded all vital fonts and icons, you’ll get the next consequence.

From the above snippet, check out the tactic onPressFab which is being handed to the FloatingButton element because the prop actionOnPress. This perform makes use of a navigation methodology offered known as navigation.navigate() with the worth of the display being handed because the argument: AddTask. Do notice that, the worth of the argument being handed must be the precise title of the display outlined earlier when configuring StackNavigator. Click on on the button, and you can be directed to the subsequent display.

Did you discover the again button on the AddTaskScreen? That is once more the place react-navigation is useful. Whereas engaged on a real-time React Native software, you usually need to use the react-navigation library if it fits your necessities. It gives easy options out of the field.

Customise the Header Part

🔗

With Native Base parts library, it’s simple to customise a header element in few strains of code. Contained in the file Header.js add the next snippet. Once more, it is a purposeful element since it’ll improve the UI and isn’t operating enterprise logic.

1import React from 'react';

2import { Header as NBHeader, Physique, Title } from 'native-base';

3

4const Header = () => {

5 return (

6 <NBHeader fashion={{ backgroundColor: '#5859f2' }}>

7 <Physique>

8 <Title fashion={{ coloration: '#ffffff' }}>Header</Title>

9 </Physique>

10 </NBHeader>

11 );

12};

13

14export default Header;

The Header element from the native-base library takes a Physique as an enter. The physique can additional comprise the rendering logic to switch the present default Header element from the native base library itself. You should use inline types and even StyleSheet object from react-native to customise the Header element as above, or another native base UI element usually. Check out the backgroundColor and the coloration to the Title. Title is the place the textual content to be displayed on this element goes.

Import this element contained in the HomeScreen.js file. Additionally, import the StatusBar element from the react-native. Because the background of the Header element goes to be a customise blue coloration, it’s higher to vary the default darkish StatusBar fashion into one thing pleasing and lightweight.

1import { View, Textual content, StyleSheet, StatusBar } from 'react-native';

2import Header from '../parts/Header';

Inside the category element, the very first thing you need to do is conceal the header that’s being offered by the stack navigator from react-navigation library. The thing navigationOptions is the best way to customise the default navigators that react-navigation renders.

1 static navigationOptions = {

2 header: null

3 }

Subsequent, contained in the render() methodology add the next earlier than the omnipresent Textual content element.

1<Header />

2<StatusBar barStyle='light-content' />

3<Textual content>Residence Display</Textual content>

The remainder of the code contained in the HomeScreen.js file stays unchanged. The StatusBar is modified by defining the a price utilizing its pre-defined prop barStyle. When utilizing a Header element from Native Base UI library, the StatusBar from React Native comes after you outline the JSX code for the header. Discover this within the above snippet. That is the way it works with Native Base library. The next display is what you get as the results of the above snippets.

Rendering an inventory of things utilizing FlatList

🔗

On this part, you’ll arrange a Checklist element that accepts mock or dummy knowledge from an array outlined as a property to the preliminary state. Open HomeScreen.js file and modify the state for now.

1state = {

2 isDataReady: false,

3 mockItems: ['First Item', 'Second Item', 'Third Item']

4};

Why dummy knowledge? Later when you’ll hook AsyncStorage API to avoid wasting and fetch the info from the database, in different phrases, enjoying round with real-time knowledge operations, there are going to be separate strategies which are going to deal with every of the info operations. For now, allow us to hook up the enterprise logic to show an inventory of things in addition to the power so as to add a brand new merchandise utilizing the modal display you will have arrange within the earlier steps.

The FlatList element is the perfect solution to show an inventory of things in a React Native software.
It’s a cross-platform element, and by default a vertical solution to show an inventory of information gadgets. It requires two props: knowledge and renderItem. The knowledge is the supply of data for the record within the type of an array. The renderItem takes one merchandise from the supply, iterates over them, and returns a formatted element to render these gadgets.

Kinds that may be utilized to a FlatList element is finished by the prop contentContainerStyle that accepts the worth of Stylesheet object. The rationale to make use of FlatList is that it’s efficiency efficient. After all, you need to use ScrollView however it renders gadgets from reminiscence, which isn’t a really performant efficient solution to show a prolonged record of things. ScrollView is a wrapper on the View element that gives the consumer interface for scrollable lists inside a React Native app.

Within the file HomeScreen.js exchange the Textual content element with following FlatList and don’t forget to import it and customized presentational element Merchandise that’s going to show every merchandise within the record.

1

2import { View, FlatList, StyleSheet, StatusBar } from 'react-native';

3import Merchandise from '../parts/Merchandise';

4

5

6<FlatList

7 knowledge={this.state.mockItems}

8 contentContainerStyle={types.content material}

9 renderItem={row => {

10 return <Merchandise textual content={row.merchandise} />;

11 }}

12 keyExtractor={merchandise => merchandise.id}

13/>;

Now open the file parts/Merchandise.js and add the next snippet.

1import React from 'react';

2import {

3 View,

4 Textual content,

5 StyleSheet,

6 TouchableOpacity,

7 Dimensions

8} from 'react-native';

9

10const { width } = Dimensions.get('window');

11

12const Merchandise = ({ textual content }) => {

13 return (

14 <View fashion={types.container}>

15 <View fashion={types.rowContainer}>

16 <Textual content fashion={types.textual content}>{textual content}</Textual content>

17 </View>

18 </View>

19 );

20};

21

22const types = StyleSheet.create({

23 container: {

24 borderBottomColor: '#5859f2',

25 borderBottomWidth: StyleSheet.hairlineWidth,

26 flexDirection: 'row',

27 alignItems: 'heart',

28 justifyContent: 'space-between'

29 },

30 rowContainer: {

31 flexDirection: 'row',

32 width: width / 2,

33 alignItems: 'heart'

34 },

35 textual content: {

36 coloration: '#4F50DC',

37 fontSize: 18,

38 marginVertical: 20,

39 paddingLeft: 10

40 }

41});

42

43export default Merchandise;

One other new React Native element to note within the above snippet is Dimensions. It helps to set the preliminary width and top of a element earlier than the appliance runs. We’re utilizing its get() methodology to accumulate the present gadget’s width and top.

Within the simulator, you’ll get the next consequence.

Studying Information utilizing AsyncStorage API

🔗

On this part, you’ll add all strategies that can comprise enterprise logic to avoid wasting and fetch the info from the AsyncStorage. This logic will probably be composed of three operations:

  • add a todolist merchandise
  • fetch all gadgets to show
  • delete an merchandise from the record
  • additionally, examine the state of every record merchandise whether or not it’s marked as accomplished or not

These operations are going to speak with the realtime knowledge on the gadget. You will use objects as an alternative of an array to retailer this stuff. AsyncStorage operates on key-value pairs and never arrays. Every object goes to be recognized by a singular ID. With the intention to generate distinctive IDs, you’ll use a module known as uuid which was put in earlier.

The construction of every todo merchandise goes to be like this:

145745c60-7b1a-11e8-9c9c-2d42b21b1a3e: {

2 id: 45745c60-7b1a-11e8-9c9c-2d42b21b1a3e,

3 textValue: 'New merchandise',

4 isCompleted: false,

5 createdAt: Date.now()

6}

But when you’ll use Objects as an alternative of an array, how are you going to iterate over every merchandise within the object? FlatList element solely takes an array to iterate. Nicely, do you bear in mind putting in a utility package deal known as lodash.values? That package deal goes to be actually useful in changing the thing into an array.

First, allow us to begin by importing all parts and customized parts required with a view to construct the appliance inside HomeScreen.js file.

1import React, { Part } from 'react';

2import {

3 FlatList,

4 View,

5 StatusBar,

6 StyleSheet,

7 AsyncStorage

8} from 'react-native';

9import uuidv1 from 'uuid/v1';

10import _values from 'lodash.values';

11import { Button, Textual content as NBText } from 'native-base';

12import { AppLoading } from 'expo';

13import * as Font from 'expo-font';

14import Header from '../parts/Header';

15import Merchandise from '../parts/Merchandise';

16import FloatingButton from '../parts/FloatingButton';

After writing these import statements, allow us to modify the preliminary state.

1state = {

2 todos: {},

3 isDataReady: false

4};

From the above snippet, do take a notice that the dummy array of information is changed by the thing todos. Subsequent, you’ll write an asynchronous methodology to load the todos gadgets from the thing that’s saved utilizing AsyncStorage API. Additionally, allow us to merge the earlier asynchronous methodology to load all of the fonts with this methodology, corresponding to the worth of the preliminary state isDataReady is ready to the boolean true solely as soon as. Additionally, you will have to switch the contents of the lifecycle methodology.

1componentDidMount = () => {

2 this.loadTodos();

3};

4

5loadTodos = async () => {

6 attempt {

7 await Font.loadAsync({

8 Roboto: require('../node_modules/native-base/Fonts/Roboto.ttf'),

9 Roboto_medium: require('../node_modules/native-base/Fonts/Roboto_medium.ttf')

10 });

11

12 const getTodos = await AsyncStorage.getItem('todos');

13 const parsedTodos = JSON.parse(getTodos);

14 this.setState({ isDataReady: true, todos: parsedTodos || {} });

15 } catch (err) {

16 alert('Software Error. Can't load knowledge.');

17 }

18};

AsyncStorage.getItem() reads something saved on the gadget database. It’s important to parse the info incoming from the storage into JSON. In case you are not parsing the info, the appliance goes to crash. When setting the state within the above snippet, the todos object is getting the default worth of an empty object is there is no such thing as a knowledge from the storage. That is additionally a necessary step to carry out and remember for different use instances with related eventualities.

Including a Todolist Merchandise

🔗

Now, allow us to add the second methodology addTodo that’s really going so as to add the brand new merchandise within the storage. The strategy defines earlier than addTodo is definitely storing the gadgets within the storage. Once more, you might be utilizing JSON.stringify() since AsyncStorage requires the info to be a string inside the only object. So when saving the merchandise in case you are not utilizing JSON.stringify() your app goes to crash.

The AsyncStorage.setItem()is the perform from the API that’s just like any key-value paired database. It takes the primary argument, todos within the snippet beneath. This argument worth goes to be the title of the shop.

The parameter newTask handed to the addTodo perform goes to be the thing. Utilizing if assertion, there’s a examine whether or not the todo merchandise being entered isn’t empty. this.setState makes use of a callback methodology that has entry to prevState object. It offers any todo merchandise that has been beforehand added to the record.

Contained in the callback, you might be first creating a brand new ID utilizing uuidv1 methodology. Then create an object known as newTodoObject which makes use of the ID as a variable for the title. This object represents every merchandise within the todo record.

Additional, create a brand new object known as newState which makes use of the prevState object, and eventually provides newTodoObject object in todoliist of things. It would sound overwhelming since lots is occurring however attempt implementing the code, you’ll perceive it higher.

1saveTodos = newToDos => {

2 const saveTodos = AsyncStorage.setItem('todos', JSON.stringify(newToDos));

3};

4

5addTodo = newTask => {

6 const newTodoItem = newTask;

7

8 if (newTodoItem !== '') {

9 this.setState(prevState => {

10 const ID = uuidv1();

11 const newToDoObject = {

12 [ID]: {

13 id: ID,

14 isCompleted: false,

15 textValue: newTodoItem,

16 createdAt: Date.now()

17 }

18 };

19 const newState = {

20 ...prevState,

21 todos: {

22 ...prevState.todos,

23 ...newToDoObject

24 }

25 };

26 this.saveTodos(newState.todos);

27 return { ...newState };

28 });

29 }

30};

Deleting a Todolist Merchandise

🔗

Just like the addTodo methodology, you’ll add one other methodology known as deleteTodo. It will care for eradicating a person merchandise from the record on the idea of id of that merchandise object. Since you might be utilizing the id of the thing each to determine the thing inside the larger object todos and assign every particular person object the identical id, the next code saves a variety of time. Eventually, utilizing the saveTodos methodology, the storage is being up to date with a remaining variety of gadgets.

1deleteTodo = id => {

2 this.setState(prevState => {

3 const todos = prevState.todos;

4 delete todos[id];

5 const newState = {

6 ...prevState,

7 ...todos

8 };

9 this.saveTodos(newState.todos);

10 return { ...newState };

11 });

12};

Mark a Todo Merchandise Test or Uncheck on completion

🔗

The final two strategies which are going to care for whether or not every particular person merchandise is checked or not are going to be represented by inCompleteTodo and completeTodo strategies. Each of those strategies are going observe which gadgets within the to-do record have been marked accomplished by the consumer or have been unmarked.

They’ll act as a toggle and solely replace the worth of isCompleted as an alternative quite updating the entire todo record merchandise object. That is once more, attainable due to a singular id for every object. Once more within the final, earlier than every of the strategies returns the brand new state, utilizing the saveTodos methodology, the storage will get an replace.

1inCompleteTodo = id => {

2 this.setState(prevState => {

3 const newState = {

4 ...prevState,

5 todos: {

6 ...prevState.todos,

7 [id]: {

8 ...prevState.todos[id],

9 isCompleted: false

10 }

11 }

12 };

13 this.saveTodos(newState.todos);

14 return { ...newState };

15 });

16};

17

18completeTodo = id => {

19 this.setState(prevState => {

20 const newState = {

21 ...prevState,

22 todos: {

23 ...prevState.todos,

24 [id]: {

25 ...prevState.todos[id],

26 isCompleted: true

27 }

28 }

29 };

30 this.saveTodos(newState.todos);

31 return { ...newState };

32 });

33};

Passing Information between completely different screens utilizing the navigation

🔗

On this part, you’ll edit every render methodology that’s chargeable for displaying the interface for the operations you outlined within the earlier sections, to occur in realtime. Allow us to begin by enhancing onPressFab methodology contained in the HomeScreen.js.

This methodology proper navigates to the AddTaskScreen. By passing an object with so as to add a brand new merchandise to the record (therefore, cross the tactic addTodo) you’ll make the most of one other benefit {that a} glossy library react-navigation gives. That’s, to cross knowledge between completely different screens.

First, edit the onPressFab methodology just like the beneath snippet.

1onPressFab = () => {

2 this.props.navigation.navigate('AddTask', {

3 saveItem: this.addTodo

4 });

5};

Subsequent, open AddTaskScreen.js and add the next snippet.

1import React, { Part } from 'react';

2import { View } from 'react-native';

3import { Type, Merchandise, Enter, Button, Textual content as NBText } from 'native-base';

4

5export class AddTaskScreen extends Part {

6 state = {

7 textual content: ''

8 };

9

10 onChangeText = occasion => {

11 this.setState({ job: occasion.nativeEvent.textual content });

12 };

13

14 onAddTask = () => {

15 this.props.navigation.state.params.saveItem(this.state.job);

16 this.props.navigation.goBack();

17 };

18

19 render() {

20 return (

21 <View>

22 <View fashion={{ marginRight: 10 }}>

23 <Type>

24 <Merchandise>

25 <Enter

26 worth={this.state.job}

27 placeholder="Enter a brand new job..."

28 autoFocus

29 clearButtonMode="all the time"

30 autoCorrect={false}

31 onChange={this.onChangeText}

32 onSubmitEditing={this.onAddTask}

33 returnKeyType={'achieved'}

34 />

35 </Merchandise>

36 </Type>

37 </View>

38 <View fashion={{ marginTop: 20 }}>

39 <Button

40 fashion={{

41 backgroundColor: '#5067FF',

42 margin: 25,

43 justifyContent: 'heart'

44 }}

45 onPress={this.onAddTask}

46 >

47 <NBText fashion={{ fontWeight: 'daring' }}>Add Job</NBText>

48 </Button>

49 </View>

50 </View>

51 );

52 }

53}

54

55export default AddTaskScreen;

The snippet above makes use of the native base library to create a managed enter kind to let the consumer add a brand new merchandise to the todo record. Subsequent, it has a button so as to add the merchandise. Because the Enter element from Native Base relies on the React Native’s TextInput, you need to use all of the props which are out there to TextInput.

Additionally, take a notice that, to create an enter area when utilizing Native base because the UI library, the Enter element must be wrapped by an Merchandise which is additional wrapped inside Type factor.

Here’s a transient overview of the props used within the above snippet.

  • worth: the worth of the textual content enter. By default, will probably be an empty string since we’re utilizing the native state to set it. Because the state updates, the worth of the textual content enter updates.
  • placeholder: identical to in HTML, a placeholder is to outline a default message within the enter area indicating as if what is anticipated.
  • onChange: is a callback that known as when the textual content enter’s textual content adjustments. Modified textual content is handed as an argument to the callback handler onChangeText. This handler accepts the textual content worth from occasion.nativeEvent.
  • clearButtonMode: a transparent button ought to seem on the suitable aspect of the textual content view. The default worth is by no means that you’re modifying to all the time within the above element.
  • returnKeyType: determines how the return key on the gadget’s keyboard ought to look. Yow will discover extra values or platform-specific values right here. A few of the values are particular to every platform.
  • autoCorrect: this prop allow us to determine whether or not to indicate the autocorrect bar together with keyboard or not. Within the present case, you will have set it to false.
  • onSubmitEditing: accommodates the enterprise the logic within the type of a callback as to what to do when the return key or enter’s submit button is pressed. We will probably be defining this callback in Essential.js.

Lastly, check out the tactic onAddTask which makes use of navigation state to avoid wasting the textual content worth of the todo merchandise. After use presses the button or the handler onSubmitEditing triggers, it’ll additional run the tactic addTodo from HomeScreen and navigate again to the HomeScreen itself, utilizing the navigation props methodology goBack().

On Clicking the Fab button, you get the next display.

Show every todo record merchandise

🔗

To show every todo record merchandise, you should have first to cross the props as proven beneath utilizing the renderItem within the FlatList.

1<Merchandise

2 isCompleted={row.merchandise.isCompleted}

3 textValue={row.merchandise.textValue}

4 id={row.merchandise.id}

5 deleteTodo={this.deleteTodo}

6 completeTodo={this.completeTodo}

7 inCompleteTodo={this.inCompleteTodo}

8/>

Subsequent, go to Merchandise.js file and add the next snippet.

1import React from 'react';

2import {

3 View,

4 Textual content,

5 StyleSheet,

6 TouchableOpacity,

7 Dimensions

8} from 'react-native';

9import { Icon } from 'native-base';

10

11const { width } = Dimensions.get('window');

12

13const Merchandise = ({

14 inCompleteTodo,

15 completeTodo,

16 textValue,

17 id,

18 deleteTodo,

19 isCompleted

20}) => {

21 toggleItem = () => {

22 if (isCompleted) {

23 inCompleteTodo(id);

24 } else {

25 completeTodo(id);

26 }

27 };

28

29 return (

30 <View fashion={types.container}>

31 <View fashion={types.rowContainer}>

32 <TouchableOpacity onPress={this.toggleItem}>

33 <Icon

34 title={isCompleted ? 'checkmark-circle' : 'radio-button-off'}

35 fashion={{ paddingLeft: 10, coloration: '#7A7AF6' }}

36 />

37 </TouchableOpacity>

38

39 <Textual content

40 fashion={[

41 styles.text,

42 {

43 opacity: isCompleted ? 0.5 : 1.0,

44 textDecorationLine: isCompleted ? 'line-through' : 'none',

45 color: isCompleted ? '#7A7AF6' : '#4F50DC'

46 }

47 ]}

48 >

49 {textValue}

50 </Textual content>

51 </View>

52 <TouchableOpacity onPressOut={() => deleteTodo(id)}>

53 <Icon title="md-trash" fashion={{ coloration: '#ABADF9', paddingRight: 10 }} />

54 </TouchableOpacity>

55 </View>

56 );

57};

58

59const types = StyleSheet.create({

60 container: {

61 borderBottomColor: '#5859f2',

62 borderBottomWidth: StyleSheet.hairlineWidth,

63 flexDirection: 'row',

64 alignItems: 'heart',

65 justifyContent: 'space-between'

66 },

67 textual content: {

68 coloration: '#4F50DC',

69 fontSize: 18,

70 marginVertical: 20,

71 paddingLeft: 10

72 },

73

74 rowContainer: {

75 flexDirection: 'row',

76 width: width / 2,

77 alignItems: 'heart'

78 }

79});

80

81export default Merchandise;

Within the above snippet, the important thing factors to notice are, utilizing Native Base, you need to use the Icon element (since you might be already loading the Ionicons library within the dad or mum element asynchronously). Subsequent, the props Merchandise parts obtain are to toggle an merchandise’s state of whether or not it’s full or not, show the textual content worth of the merchandise and lastly, a button to delete the merchandise itself.

Save the element file, hop again on the simulator file, and take a look at including one or many gadgets on this record.

See all the pieces works. Even on refreshing the app, and the gadgets don’t disappear.

Bonus Part: Including a Section

🔗

On this part, you’ll separate the UI for managing the finished record of things and gadgets which are pending to be achieved. To supply this function, you’ll use Native Base library solely.

Retaining the info supply identical from the storage API, let modify the state by including yet one more property. Open HomeScreen.js file and add the next.

1

2state = {

3 todos: {},

4 isDataReady: false,

5 filter: 'Todo'

6};

The worth of the filter goes to be Todo by default. This implies it’ll present the pending todo record gadgets as the house display to the consumer.

Subsequent, you’ll add one other handler perform known as filteredItems. This methodology will consider the worth of the state and filter the values from the todos to match the state. Once more, to make use of JavaScript filter methodology, you’ll convert todos object utilizing lodash methodology _values.

1filteredItems = () => {

2 if (this.state.filter === 'Todo') {

3 return _values(this.state.todos).filter(i => {

4 return !i.isCompleted;

5 });

6 }

7 if (this.state.filter === 'Full') {

8 return _values(this.state.todos).filter(i => {

9 return i.isCompleted;

10 });

11 }

12 return this.state.todos;

13};

Subsequent, allow us to modify the render methodology to attain the specified consequence. Contained in the render methodology, you’ll add a brand new UI factor from Native base known as Section. That is going to show two buttons, every of which may be activated when pressed. The activation of every this button will depend on the worth of the state property filter.

1

2import { Button, Textual content as NBText, Section } from 'native-base'

3

4

5

6const { isDataReady, filter } = this.state

7

8

9

10 <View fashion={types.contentHeader}>

11 <Section fashion={{ backgroundColor: '#ffffff' }}>

12 <Button energetic={filter === 'Todo'} onPress={() => this.setState({ filter: 'Todo' })}>

13 <NBText>Todo</NBText>

14 </Button>

15 <Button

16 final

17 energetic={filter === 'Full'}

18 onPress={() => this.setState({ filter: 'Full' })}

19 >

20 <NBText>Full</NBText>

21 </Button>

22 </Section>

23 </View>

24

25

26

27contentHeader: {

28 alignItems: 'heart',

29 justifyContent: 'heart'

30}

Lastly, change the worth of the knowledge prop on FlatList and set it to the merchandise returned from the tactic filteredItems().

1<FlatList

2 knowledge={_values(this.filteredItems())}

3

4/>

You’re going to get the next consequence.

Conclusion

🔗

Congratulations! You’ve gotten simply discovered the best way to construct an offline cell software utilizing newest tech stack and libraries like React Native, Expo, and Native Base element UI. You’ve gotten discovered many key factors on this tutorial, and I hope you loved following it, and studying it. Use the data you will have gained on this tutorial in a realtime software and present it to your friends. The chances to reinforce this software or the use the data is countless.


I am a software program developer and a technical author. On this weblog, I write about Technical writing, Node.js, React Native and Expo.

Presently, working at Expo. Beforehand, I’ve labored as a Developer Advocate, and Senior Content material Developer with firms like Draftbit, Vercel and Crowdbotics.

RELATED ARTICLES

Most Popular

Recent Comments