简体   繁体   English

React Native初始数据库

[英]React Native initial database

I want to develop a React Native app, and I want to have locally stored some data of the format: 我想开发一个React Native应用,并且我想在本地存储一些格式的数据:

[
  {
    "id": 1,
    "text": "Lorem ipsum",
    "viewed": false
  },
  {
    "id": 2,
    "text": "Second lorem",
    "viewed": false
  },
  {
    "id": 3,
    "text": "Last lorem",
    "viewed": false
  }
]

I want this data to be available when the user first downloads the app. 我希望该数据在用户首次下载该应用程序时可用。 Then based on the user's navigation, the corresponding data in the db will change the viewed flag to true. 然后,基于用户的导航,数据库中的相应数据将把viewed标志更改为true。 This has to be persistent when the app will be updated by the user on the next version. 当用户将在下一版本中更新应用程序时,此设置必须保持不变。

Any tips/ideas on how to achieve this? 有关如何实现此目标的任何提示/想法?

Currently I'm looking into Realm.io but I'm not sure if this is the right tool for me. 目前,我正在研究Realm.io,但不确定是否适合我。

You can use AsyncStorage for that like so: 您可以这样使用AsyncStorage

const data = [
  {
    "id": 1,
    "text": "Lorem ipsum",
    "viewed": false
  },
  {
    "id": 2,
    "text": "Second lorem",
    "viewed": false
  },
  {
    "id": 3,
    "text": "Last lorem",
    "viewed": false
  }
]

try {
  await AsyncStorage.setItem(
    'SOME_KEY', JSON.stringify(data)
  );
} catch (error) {
  // Handle error 
}

Later on if you want to fetch/change you can do: 稍后,如果您要获取/更改,可以执行以下操作:

AsyncStorage.getItem('SOME_KEY', (err, result) => {
  console.log(JOSN.parse(result));
});

If data is more than pouchDb is suggested option. 如果数据大于pouchDb,则建议使用该选项。

You can install it with 您可以使用

npm install pouchdb-react-native --save

Simple Demo 简单演示

import PouchDB from 'pouchdb-react-native'
const db = new PouchDB('mydb')

// use PouchDB
db.get('4711')
  .then(doc => console.log(doc))

Advance Demo 预先演示

'use strict'

import React from 'react'
import {
  AsyncStorage,
  ListView,
  Navigator,
  StyleSheet,
  Text,
  TextInput,
  TouchableHighlight,
  View
} from 'react-native'

import ActionButton from 'react-native-action-button'
import PouchDB from 'pouchdb-react-native'

const localDB = new PouchDB('myDB')
console.log(localDB.adapter)

AsyncStorage.getAllKeys()
  .then(keys => AsyncStorage.multiGet(keys))
  .then(items => console.log('all pure Items', items))
  .catch(error => console.warn('error get all Items', error))

export default React.createClass({
  getInitialState () {
    const updateDocs = () => {
  localDB.allDocs({include_docs: true, limit: null})
    .then(result => {
      const items = result.rows.map(row => row.doc)
      const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1.id !== r2.id})
      this.setState({
        dataSource: ds.cloneWithRows(items),
        count: items.length
      })
    })
    .catch(error => console.warn('Could not load Documents', error, error.message))
}

localDB.changes({since: 'now', live: true})
  .on('change', () => updateDocs())

updateDocs()

return {
  dataSource: null,
  syncUrl: 'http://localhost:5984/test'
}
  },
  render () {
const renderScene = (route, navigator) => (
  <View style={{flex: 1, marginTop: 20, backgroundColor: '#FFFFFF'}}>
    {route.render()}
  </View>
)

const renderMain = () => {
  const insertAttachment = () => {
    const doc = {
      'title': 'with attachment',
      '_attachments': {
        'att.txt': {
          'content_type': 'text/plain',
          'data': 'TGVnZW5kYXJ5IGhlYXJ0cywgdGVhciB1cyBhbGwgYXBhcnQKTWFrZS' +
                  'BvdXIgZW1vdGlvbnMgYmxlZWQsIGNyeWluZyBvdXQgaW4gbmVlZA=='
        }
      }
    }

    localDB.post(doc)
      .then(result => console.log('save.attachment', result))
      .catch(error => console.warn('save.attachment.error', error, error.message, error.stack))
  }

  const insertRecords = count => {
    for (let index = 0; index < count; index++) {
      localDB.post({
        text: `Record ${index}/${count}`
      })
    }
  }

  const destroy = count => {
    localDB.destroy()
      .then(() => console.log('destroyed'))
      .catch(error => console.warn('destroyed', error))
  }

  const { dataSource } = this.state

  const renderSeparator = (sectionID, rowID) => (
    <View
      key={rowID}
      style={{borderColor: '#969A99', borderBottomWidth: StyleSheet.hairlineWidth}} />
  )

  const renderRow = (row) => {
    const updateItem = () => {
      const newRow = {...row}
      newRow.clickCount = newRow.clickCount ? newRow.clickCount + 1 : 1

      localDB.put(newRow)
        .then(result => console.log('Updated Item', result))
        .catch(error => console.warn('Error during update Item', error))
    }

    return (
      <TouchableHighlight onPress={updateItem}>
        <View key={row._id}>
          <Text style={{fontWeight: 'bold'}}>{row._id}</Text>
          <Text>{JSON.stringify(row, null, 4)}</Text>
        </View>
      </TouchableHighlight>
    )
  }

  const renderList = () => (
    <ListView
      dataSource={dataSource}
      renderRow={renderRow}
      renderSeparator={renderSeparator}
      enableEmptySections />
  )

  return (
    <View style={{flex: 1}}>
      <View>
        {!!this._sync && <Text style={{fontWeight: 'bold'}}>{this.state.syncUrl}</Text>}
        <Text style={{fontWeight: 'bold'}}>Count: {this.state.count}</Text>
      </View>
      <View
        style={{borderColor: '#969A99', borderBottomWidth: StyleSheet.hairlineWidth}} />
      {!dataSource
        ? (<Text>Loading...</Text>)
        : renderList()
      }
      <ActionButton buttonColor='#78B55E'>
        <ActionButton.Item
          buttonColor='#005BFF'
          title='Destroy Database'
          onPress={destroy}>
          <Text>destroy</Text>
        </ActionButton.Item>
        <ActionButton.Item
          buttonColor='#005BFF'
          title='Insert Attachments'
          onPress={insertAttachment}>
          <Text>attach</Text>
        </ActionButton.Item>
        <ActionButton.Item
          buttonColor='#005BFF'
          title='Insert 250 Records'
          onPress={() => insertRecords(250)}>
          <Text>insert</Text>
        </ActionButton.Item>
        <ActionButton.Item
          buttonColor='#005BFF'
          title='Sync'
          onPress={() => this._navigator.push({name: 'Sync', render: renderSync})}>
          <Text>sync</Text>
        </ActionButton.Item>
        <ActionButton.Item
          buttonColor='#005BFF'
          title='Add Item'
          onPress={() => this._navigator.push({name: 'AddItem', render: renderAddItem})}>
          <Text>+</Text>
        </ActionButton.Item>
      </ActionButton>
    </View>
  )
}

const renderButton = (text, onPress) => {
  return (
    <TouchableHighlight
      onPress={onPress}
      style={{
        flexDirection: 'column',
        paddingTop: 3,
        paddingBottom: 3,
        marginLeft: 10,
        marginRight: 10,
        backgroundColor: '#78B55E',
        borderRadius: 5
      }}>
      <Text
        style={{
          flex: 1,
          fontSize: 18,
          fontWeight: 'bold',
          color: '#FFFFFF',
          paddingLeft: 10,
          paddingRight: 10,
          paddingTop: 2,
          alignSelf: 'center'
        }}>
        {text}
      </Text>
    </TouchableHighlight>
  )
}

const renderSync = () => {
  const addSync = () => {
    if (this._sync) {
      this._sync.cancel()
      this._sync = null
    }

    if (this.state.syncUrl) {
      const remoteDb = new PouchDB(this.state.syncUrl, {ajax: {cache: false}})
      this._sync = PouchDB.sync(localDB, remoteDb, {live: true, retry: true})
        .on('error', error => console.error('Sync Error', error))
        .on('change', info => console.log('Sync change', info))
        .on('paused', info => console.log('Sync paused', info))
    }

    this._navigator.pop()
  }

  return (
    <View style={{flex: 1}}>
      <TextInput
        style={{
          height: 40,
          lineHeight: 40,
          fontSize: 16,
          paddingLeft: 10,
          paddingRight: 10
        }}
        autoFocus
        keyboardType='url'
        clearButtonMode='always'
        placeholder='enter URL'
        onChangeText={(text) => this.setState({syncUrl: text})}
        value={this.state.syncUrl} />
      {renderButton('Add Sync', addSync)}
    </View>
  )
}

const renderAddItem = () => {
  const addItem = () => {
    localDB.post(JSON.parse(this.state.newItem))
      .then(result => {
        this.setState({newItem: ''})
        this._navigator.pop()
      })
      .catch(error => console.error('Error during create Item', error, error.message))
  }

  return (
    <View style={{flex: 1}}>
      <TextInput
        style={{
          height: 340,
          lineHeight: 40,
          fontSize: 16,
          paddingLeft: 10,
          paddingRight: 10
        }}
        autoFocus
        clearButtonMode='always'
        multiline
        placeholder='JSON Object here'
        onChangeText={(text) => this.setState({newItem: text})}
        value={this.state.newItem} />
      {renderButton('Add Item', addItem)}
    </View>
  )
}

return (
  <View style={{flex: 1}}>
    <Navigator
      ref={navigator => { this._navigator = navigator }}
      renderScene={renderScene}
      initialRoute={{name: 'Main', render: renderMain}}
    />
  </View>
)
  }
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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