
- データを保存する方法
- AsyncStorageの実装方法
について解説していきます。
1. 概要
アプリを作る上で、タスクキルした時に、データが消えないようにデータを保存したい!
と言う時があると思います。「データを保存するとしたらデータベース??でもデータベースは難しそう」と思う方は、少なからずいると思います。
そこでAsyncStorageの登場です。
2. AsyncStorageとは?
AsyncStorageは、
データベースを使わずにスマホのストレージにデータを永続的に保存することが可能
なライブラリです。
公式ドキュメント: AsyncStorage
3. 使い方
AsyncStorageは、
setItem()メソッド
でデータを保存し、
getItem()メソッド
で保存したデータを取得します。
3.1 import
以下のようにreact-nativeからAsyncStorageをインポートします。
1 |
import { AsyncStorage } from 'react-native'; |
3.2 setItem()メソッド
AsyncStorage.setItem(key, value);
を使って、
保存したいデータ(value)をkeyに保存することができます。
ただし、AsyncStorageには、string型(文字列)しか保存できない為、保存処理の前に一処理が必要です。
JSON.stringify({})を使用して、
データ構造をstring型(文字列)に変換してからsetItemで保存します。
1 2 3 4 5 6 7 8 |
saveItem = async(counter) => { try { const todoString = JSON.stringify(counter); await AsyncStorage.setItem(DATA, todoString); } catch (e) { console.log(e) } } |
3.3 getItem()メソッド
AsyncStorage.getItem(key);
を使うことで、
keyに保存してあるデータを呼び出すことができます。
文字列で保存されているため、JSON.parse()を使って、
文字列を元のデータ構造に変換してから値を使います。
1 2 3 4 5 6 7 8 9 10 11 |
loadItem = async () => { try { const todoString = await AsyncStorage.getItem(DATA); if(todoString) { const counter = JSON.parse(todoString); this.setState({counter: counter}); } } catch (e) { console.log(e) } } |
3.4 componentDidMount()
いつ、どこで保存したデータを取得すればいいのか分からないと言う方は、componentDidMount()で取得すれば問題ないと思います。
componentDidMount()は、コンポーネントが初めてレンダリングされる時に呼び出される為、
componentDidMount()でgetItem()メソッドを呼び出して、保存していたデータを任意の値に設定することができます。
以下の4.1 サンプルコードを参考にして実装してみてください!
4. 実装例
4.1 サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
import React from 'react'; import { View, Text, StyleSheet, TouchableHighlight, TouchableOpacity, AsyncStorage, } from 'react-native'; import { Header } from 'react-native-elements'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; const DATA = "@DATA" export default class App extends React.Component { constructor(props) { super(props); this.state = { counter: 0, } } componentDidMount() { this.loadItem() } loadItem = async () => { try { const todoString = await AsyncStorage.getItem(DATA); if(todoString) { const counter = JSON.parse(todoString); this.setState({counter: counter}); } } catch (e) { console.log(e) } } // AsyncStorageからTODOを保存 saveItem = async(counter) => { try { const todoString = JSON.stringify(counter); await AsyncStorage.setItem(DATA, todoString); } catch (e) { console.log(e) } } plusCounter = () => { this.setState({counter:this.state.counter + 1}) this.saveItem(this.state.counter + 1) } minusCounter = () => { if(this.state.counter == 0) { this.setState({counter:0}) } else { this.setState({counter:this.state.counter - 1}) this.saveItem(this.state.counter - 1) } } reset = () => { this.setState({counter: 0}) this.saveItem(0) } render() { const { counter } = this.state return ( <View style={styles.container}> {/* ヘッダー */} <Header centerComponent={{ text: 'Counter', style: { color: 'lightblue', fontSize: 26, fontFamily: 'Baskerville-Bold' } }} backgroundColor="black" /> <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }} > {/* カウンター表記 */} <View> <Text style={styles.counter}>{counter}</Text> </View> <View style={styles.icon}> {/* マイナスボタン */} <TouchableHighlight style={ [styles.text, { marginRight: 50, backgroundColor: "hsla(210, 90%, 55%, 0.6)" } ]} activeOpacity={0.6} underlayColor="hsla(210, 90%, 40%, 0.8)" onPress={() => this.minusCounter()} > <Icon name="minus" size={40} color="black" /> </TouchableHighlight> {/* プラスボタン */} <TouchableHighlight style={ [styles.text, { marginLeft: 50, backgroundColor: "hsla(0, 90%, 55%, 0.6)" } ]} activeOpacity={0.6} underlayColor="hsla(0, 90%, 40%, 0.8)" onPress={() => this.plusCounter()} > <Icon name="plus" size={40} color="black" /> </TouchableHighlight> </View> <View style={{position: "absolute", bottom: 50}}> {/* リセットボタン */} <TouchableOpacity style={styles.resetView} onPress={() => this.reset()} > <Text style={styles.resetText}>リセット</Text> </TouchableOpacity> </View> </View> </View> ); } } const styles = StyleSheet.create({ container:{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: "hsla(0, 0%, 0%, 0.05)" }, counter: { flex: 0.4, fontSize: 90, fontWeight: "bold", }, icon: { flexDirection: "row", }, text: { borderColor: "black", borderWidth: 2, borderRadius: 10, alignItems: "center", justifyContent: "center", height: 80, width: 80, backgroundColor: "white", shadowColor: "black", shadowOffset: { height: 4, width: 4 }, shadowRadius: 3, shadowOpacity: 0.6, }, resetView: { shadowColor: "black", shadowOffset: { height: 4, width: 4 }, shadowRadius: 3, shadowOpacity: 0.6, borderColor: "black", borderWidth: 1, borderRadius: 10, alignItems: "center", backgroundColor: "hsla(60, 90%, 55%, 0.6)", }, resetText: { fontSize: 30, padding: 10, color: "white", }, }); |
4.2 結果
シミュレータでリロードしても値が変わっていないことが確認できると思います。