React NativeでRealmを使ったアプリ設定の簡易保存


iOSでは`UserDefaults`, Androidでは`PreferenceManager`と簡単に保存する手段がありますが、それらをReact Native上でRealmで代用してみます。

## サンプル 簡易版
```js
import Realm from 'realm';

const keyPreference = "Preference";

const Preference = {
    name: keyPreference,
    primaryKey: 'id', // プライマリキーを指定
    properties: {
        id: 'int', // プライマリキーとして扱う (int型)
        title: 'string' // 任意のプロパティ (string型)
    }
};

const realmPreference = () => {
    const realm = new Realm({
        schema: [Preference] // スキーマを設定
    });
    
    if (realm.objects(keyPreference).length == 0) {
        // 初回はデータがないのでレコードを1つ作る
        realm.write(() => {
            realm.create(keyPreference, {
                id: 0,
                title: ''
            });
        });
    }

    return realm;
};

// titleプロパティの値を取得
export const getTitle = () => {
    const realm = realmPreference();
    // id = 0 のレコードを取得
    const obj = realm.objects(keyPreference).filtered("id = 0");
    return obj[0].title;
};

// titleプロパティに値をセット
export const setTitle = (item) => {
    // 型の確認
    if (typeof item !== 'string') {
        return;
    }
    const realm = realmPreference();
    // id = 0 のレコードをアップデート
    realm.write(() => {
        realm.create(keyPreference, {
            id: 0,
            title: item
        }, true);
    });
};
```

## 使い方

```js
import * as preference from './preference';
...
preference.setTitle("The cat's out of the bag.");
preference.getTitle();
```

## プロパティを追加したいとき (Migration)
```js
import Realm from 'realm';

const keyPreference = "Preference";

const Preference = {
    name: keyPreference,
    primaryKey: 'id', // プライマリキーを指定
    properties: {
        id: 'int', // プライマリキーとして扱う (int型)
        title: 'string', // 任意のプロパティ (string型)
        isActive: 'bool' // プロパティを追加 (boolean型)
    }
};

const realmPreference = () => {
    const realm = new Realm({
        schema: [Preference], // スキーマを設定
        schemaVersion: 2, // 新しいバージョンを指定
        migration: (oldRealm, newRealm) => {
            const oldObjs = oldRealm.objects(keyPreference);
            const newObjs = newRealm.objects(keyPreference);
            const oldVersion = oldRealm.schemaVersion;
            if (oldVersion < 2) {
                // 既存のプロパティを使って新しいプロパティの値を決めたい場合
                for (let i = 0; i < oldObjs.length; i++) {
                    newObjs[i].isActive = (oldObjs[i].title.length > 0);
                }
            }
        }
    });
    
    if (realm.objects(keyPreference).length == 0) {
        // 初回はデータがないのでレコードを1つ作る
        realm.write(() => {
            realm.create(keyPreference, {
                id: 0,
                title: '',
                isActive: false
            });
        });
    }

    return realm;
};


const getPreference = () => {
    const realm = realmPreference();
    const obj = realm.objects(keyPreference).filtered("id = 0");
    return obj[0];
};

const updatePreference = (item) => {
    if (typeof item !== 'object') {
        return;
    }
    const realm = realmPreference();
    // update
    realm.write(() => {
        realm.create(keyPreference, {
            id: 0,
            ...item
        }, true);
    });
};

export const getTitle = () => {
    return getPreference().title;
};

export const setTitle = (item) => {
    if (typeof item !== 'string') {
        return;
    }
    updatePreference({title: item});
};

export const getIsActive = () => {
    return getPreference().isActive;
};

export const setIsActive = (item) => {
    if (typeof item !== 'boolean') {
        return;
    }
    updatePreference({isActive: item});
};

```