2016-03-09 4 views
11

Каковы лучшие практики/шаблоны, превращающие realm в реактивный источник данных в ответном родном приложении? Специально для presentational and container components pattern?Realm & React Native - Лучшая практика для внедрения автоматических обновлений?

Вот пример, который я хотел бы сделать реактивным: Realm with React Native

docs on auto-updates/change-events немного тонким и official example не использует эту функцию (к моему знанию).

ответ

13

Вы можете сделать свой пример реактивным, подписавшись на события и обновив ui, когда вы получаете событие изменения. Прямо сейчас события отправляются только при совершении транзакций записи, но в будущем будут добавляться более мелкие изменения. На данный момент вы можете добавить следующий конструктор для обновления пользовательского интерфейса на изменения:

constructor(props) { 
    super(props); 
    this.realm = new Realm({schema:[dogSchema]}) 
    this.realm.addListener('change',() => { 
    this.forceUpdate() 
    }); 
} 

Вы должны держать на экземпляр Realm, чтобы сохранить уведомления в живых, и вы можете использовать этот экземпляр Realm в остальной части компонента.

Вместо вызова forceUpdate, вы могли бы вместо того, чтобы установить состояние или реквизит компонента прослушивателя событий для запуска обновления, например, так:

constructor(props) { 
    super(props); 

    this.realm = new Realm({schema:[dogSchema]}) 

    this.state = {...}; // Initial state of component. 

    this.realm.addListener('change',() => { 
    this.setState({...}); // Update state instead of using this.forceUpdate() 
    }); 
} 
+0

Спасибо @ Ари, как я мог установить опоры в приемник событий ?. Замените 'this.forceUpdate()' на 'super (props)'? – ThorbenA

+0

Для вашего примера вы, вероятно, захотите вместо этого вызвать 'setState'. Вместо того, чтобы вычислять 'dogProp' в' render', вы вместо этого помещаете его в 'state', который автоматически запускает повторную визуализацию. Что-то вроде 'this.setState ({dogProp: this.realm.objects ('Dog'). Length})'. Вы также хотели бы реализовать 'getInitialState'. – Ari

+0

еще раз спасибо @Ari. Любой способ сделать это без введения локального состояния компонента? (Я использую Redux) – ThorbenA

7

Я думаю, @Ari дал мне хороший ответ для redux людей как я тоже боролся. Я не уверен, что он является неизменным, но он работает !

Я просто отправлю getVehicles действие внутри addListener и оно просто работает!

Ниже является компонентом пользовательского интерфейса, функция конструктора которого делает магию!

//- importing my realm schema 
 
import realm from '../../db/models'; 
 
//- Importing my action 
 
import { getVehicles } from './../../actions/vehicle'; 
 

 

 
@connect((store) => { 
 
    return { 
 
     vehicle: store.vehicle.vehicles 
 
    } 
 
}) 
 
export default class Devices extends Component { 
 
    constructor(props) { 
 
     super(props); 
 

 
     realm.addListener('change',() => { 
 
      props.dispatch(getVehicles()); 
 
     }); 
 

 
    } 
 
}

Ниже является дб файл/модели, используемые там в конструкторе.

import Realm from 'realm'; 
 

 
class VehicleSchema {}; 
 

 
VehicleSchema = { 
 
    name: 'vehicleInfo', 
 
    properties: { 
 
     vehicleName: 'string', 
 
     vehicleNumber: 'string', 
 
     vehiclePassword: 'string', 
 
     vehiclePasswordTrigger: 'bool', 
 
     vehicleType: 'string', 
 
     vehiclePicture: { type: 'data', optional: true } 
 
    } 
 
}; 
 

 
export default new Realm({schema: [VehicleSchema]});

Ниже это действия/файл транспортного средства, который получает отправляется в конструкторе выше.

import { queryVehicle } from './../db/queryVehicle'; 
 

 
export function getVehicles() { 
 

 
    const vehicles = queryVehicle(); 
 

 
    return function(dispatch) { 
 
     dispatch({type: "GOT_VEHICLES", payload: vehicles}); 
 
    } 
 
}

Ниже моя функция queryVehicle, что делает обработку запросов с именем в файле действий выше.

import vehicleModel from './models'; 
 

 
const queryVehicle = (queryInfo="vehicleInfo", filter='') => { 
 

 
    const objects = vehicleModel.objects(queryInfo); 
 

 
    if(filter.length === 0) return objects; 
 

 
    let results = objects.filtered(filter); 
 
    return results; 
 

 

 
}; 
 

 
export { queryVehicle };

отказ от ответственности Я не знаю, если этот код выглядит достаточно неизменны, или после хорошей Redux практики, потому что я только начиная с Redux так дайте мне некоторые комментарии советуя если г «Я делаю что-то неправильно.

Я также думаю, что реализация reducer не имеет большого значения в этом здесь.

1

Недавно возникла проблема с автоматическим обновлением Realm ListView. Когда строки ListView имеют разную высоту, вы можете получить перекрытие строк в пользовательском интерфейсе. Ниже был единственный способ, с помощью которого ListView можно было повторно визуализировать, не вызывая перекрытия пользовательского интерфейса. Мне кажется немного «грязным», поэтому, если есть лучший способ, я приветствую вход. Но пока это прекрасно работает; если кто-нибудь еще столкнется с этой проблемой.

В основном это просто вытирает DataSource, затем вставляет его снова с помощью SetState обратного вызова, когда есть insertions или deletions, но modifications просто катиться через и автоматическое обновление.

let feed = this.props.store.feed; 

feed.addListener((name, changes) => { 
    if (changes.insertions.length || changes.deletions.length) { 
     this.setState({dataSource: this.ds.cloneWithRows([])}, 
      () => this.setState({dataSource: this.ds.cloneWithRows(feed)}) 
     ); 
    } else { 
     this.setState({dataSource: this.ds.cloneWithRows(feed)}); 
    } 
}); 
Смежные вопросы