React native and MobX: How to create a global store? - javascript

I am currently trying to implement a mobx storage which I can call from everywhere like so:
import {userStore} from '../UserStore.js';
At the end of the file, my export functionality looks as follows:
const userStore = new UserStore();
export {userStore};
As I understand, everytime I call the import functionality, the object gets re-created with which multiple files that import UserStore don't share the same variables.
However, I want that every file that imports UserStore imports the same object with the exact same variables. How can I achieve this? I am not fully sure how to achieve, so any ideas and examples would be appreciated :)
The full code (for the UserStore.js declaration), if of any help, is as follows (look at the very bottom for the export statement)
import {observable, computed, action} from 'mobx';
import {ObservableMap, toJS} from 'mobx';
import {Fb} from './firebase.js';
class UserStore {
/** GPS */
#observable usrLng = 0.0;
#observable usrLat = 0.0;
#observable watchID = null;
#action
watchCurLocation() {
this.watchID = navigator.geolocation.watchPosition((position) => {
console.log("Recording GPS data from within the Store!!");
this.usrLat = parseFloat(position.coords.latitude);
this.usrLng = parseFloat(position.coords.longitude);
}, (error) => console.log(JSON.stringify(error)), {
enableHighAccuracy: true,
timeout: 2000,
maximumAge: 1000
});
}
#action
clearWatch() {
navigator.geolocation.clearWatch(this.watchID);
}
/*/ GPS */
/** BIKE BOOKING */
#observable interestBikeNo = -1;
#observable bookedBikeNo = -1;
#action
setInterestBikeNo(bn) {
this.interestBikeNo = bn;
}
}
const userStore = new UserStore();
export {userStore};

You simply need a singleton instance of UserStore class
Sample demo
let localInstance = null;
export class Apple {
static newInstance() {
if (! localInstance)
localInstance = new Apple();
return localInstance;
}
}
// usage
import {Apple} from './apple';
const instance = Apple. newInstance();
In your case, you can use a simple function
import {observable, computed, action} from 'mobx';
import {ObservableMap, toJS} from 'mobx';
import {Fb} from './firebase.js';
class UserStore {
// omitted
}
let userStore;
export function getUserstore() {
if (!userStore)
userStore = new UserStore();
return userStore;
};
Somewhere in code
// instead of
import {userStore} from './someUserStoreModule';
// use
import {getUserstore} from './someUserStoreModule';
const userStore = getUserstore();

Related

Svelte: How to import all stores from a file without listing them all?

Is it possible to import all exported stores from a file in a single line? Instead of listing them all like so:
import { store1, store2, store3 } from './stores.js';
Is there a way to do something like this:
import { * } from './stores.js';
or is there some other workaround?
If not, what is the recommended architecture to avoid the need for this?
I do not know if it satisfies your needs but you could export all stores in an object
//main.svelte
<script>
import stores from './stores.js';
let count_value, store1_v, store2_v;
stores.count.subscribe(value => {
count_value = value;
});
stores.store1.subscribe(value => {
store1_v = value;
});
stores.store2.subscribe(value => {
store2_v = value;
});
</script>
<h1>The count is {count_value}</h1>
<h1>The count is {store1_v}</h1>
<h1>The count is {store2_v}</h1>
//stores.js
import { writable } from 'svelte/store';
export const count = writable(0);
export const store1 = writable(4565465);
export const store2 = writable(345);
export default {
count,
store1,
store2,
}
Another option for stores would be
//stores.js
import { writable } from 'svelte/store';
export default {
count: writable(0),
store1: writable(4565465),
store2: writable(345),
}

Webpack ES6 modules multiple class app organization

I'm building an app with webpack for the first time and i'm trying to wrap my head around organizing class files. I'm having trouble getting the code to work. I'm still new to ES6 and such, so my code below is probably very wrong but i'm not sure its my approach/concept or its my syntax.
entry is index.js and I also have these files
import App from './js/app.js';
import User from './js/user.js';
import Guest from './js/guest.js';
const app = new App();
const user = new User();
const guest = new Guest();
$(document).ready(function () {
app.DatabaseStore.senddata();
console.log( user.getall() );
});
src/js/app.js the main global method/variable class
import CookieStore from './cookie.js';
import DatabaseStore from './database.js';
export default class App {
constructor() {
this.cookieStore = new CookieStore();
this.databaseStore = new DatabaseStore();
}
gettime() {
return 'time';
}
}
src/js/user.js methods that are for users
import App from './app.js';
export default class User extends App {
constructor() {
this.mydata = App.cookieStore.getData();
console.log(this.mydata );
}
getall() {
return ['foo', 'bar', 'baz'];
}
}
src/js/guest.js methods that are for guests
import App from './app.js';
export default class Guest extends App {
constructor() {
this.mydata = App.cookieStore.getData();
}
}
src/js/cookie.js cookie manipulating methods
export default class CookieStore {
constructor() {}
mydata() {return 'foo';}
}
src/js/database.js firebase methods
export default class DatabaseStore {
constructor() {}
senddata() {
this.mydata = App.cookieStore.getData();
}
You are trying to access instance property statically. You need to create an instance of App class before trying to access cookieStore property. You can create an instance and export it in your app.js to have singleton instance.
//in your app.js
export const app = new App();
in other files
import {app} from './js/app.js'
app.cookieStore.getData();

How to create a singleton observable?

I have a singleton class :
let instance = null;
class SingletonClass {
constructor() {
if (!instance) {
instance = this;
}
return instance;
}
get types() {
return this._types;
}
set types(value) {
this._types = value;
}
}
export default SingletonClass;
and i use it like this:
import SingletonViews from './SingletonClass';
export default class MyStore {
this._singletonClass = new SingletonClass();
#observable types;
this.types= this._singletonClass.types; //i dont know what to do here to bind this two together
}
But whenever this._singletonClass.types updated the types observable wont. what can i do about it?
can i have a #observable singleton or can i bind its proprty to a #observable
Your "singleton" is not an observable itself and what is your intention? just proxy the singleton values?
Since you don't seem to need to initialize your singleton, I'd rewrite it this way:
Singleton
import * as mobx from 'mobx'
const {observable, action} = mobx
class SingletonClass {
#observable types
#action setTypes (value) {
this.types = value;
}
}
export default new SingletonClass()
MyStore
import singletonClass from './SingletonClass'
export default class MyStore {
singletonClass = singletonClass
}
Now you can use your store somewhere in your app and observe your singleton.

Pass data from react.js Store to Component in a clean way following flux pattern

following the Flux pattern I'm trying to update my component and pass some values (a string and a boolean in this specific case) via the store.
I could not find any non-hacky way to solve this yet i.e. using global vars in the Store and use a getter function in the Store which is called from the component on ComponentWillMount(), not a nice solution.
Here's a stripped down code example to show what im trying to achieve:
ExampleStore.js
import AppDispatcher from '../appDispatcher.jsx';
var displayimportError = false;
var importedID = '';
import axios from 'axios';
class ExampleStore extends EventEmitter {
constructor() {
super();
}
importId(id) {
let self = this;
// fetch data from BE
axios.get('foo.com').then(function(response) {
if (response.data && response.data.favoriteEntries) {
displayimportError = false;
}
self.emitChange();
}).catch(function(error) {
console.log(error);
displayimportError = true;
importedID = id;
self.emitChange();
// now update component and pass displayimportError and
// importedID.
// best would to component.receiveUpdateFromStore(param); but
// it's giving receiveUpdateFromStore is not function back
});
}
}
var favObj = new ExampleStore();
AppDispatcher.register(function(payload) {
var action = payload.action;
switch (action.actionType) {
case 'UPDATE_ID':
favObj.importId(action.data);
break;
}
return true;
});
export default favObj;
As mentioned in the Comment above the best solution in my eyes so far would be to call a function in the component from the store i.e component.receiveUpdateFromStore(param); and then update the component state within that function but even though they seem to be im/exported correctly to me it is returning receiveUpdateFromStore is undefined.
Any other idea how to solve this is appreciated.
//example component
import React from 'react';
import ReactDom from 'react-dom';
import ExampleStore from '../stores/ExampleStore.jsx';
class ExampleComponent extends React.Component {
constructor(props) {
super(props);
}
receiveUpdateFromStore(param) {
this.setState({'exampleText': param.text, 'exampleBoolean': param.bool});
}
render() {
return <div className="foo">bar</div;
}
}
export default ExampleComponent;
Any idea how to pass data from store to a component and update component state in a nice way?
I would hang your store state on the store class instance itself -- something like this.state.displayimportError = true -- and then have the component subscribe to the store:
import React from 'react';
import ExampleStore from '../stores/ExampleStore.jsx';
class ExampleComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
importError: ExampleStore.state.displayimportError,
};
}
componentWillMount() {
ExampleStore.on( 'change', this.updateState );
}
componentWillUnmount() {
ExampleStore.removeListener( 'change', this.updateState );
}
updateState = () => {
this.setState( state => ({
importError: ExampleStore.state.displayimportError,
})
}
render() {
return <div>{ this.state.importError }</div>
}
}
NOTE: Above code untested, and also using class properties/methods for binding updateState.

Dependency Injection Constructor that takes arguments

I'm building an Aurelia app that uses "Models" for every type of data object.
All my Models look something like this:
export class Item {
id = null;
name = '';
description = '';
constructor (data) {
Object.assign(this, data);
}
}
And I later create objects like this:
export class SomeViewModel {
activate () {
this.myItem = new Item({
name: 'My Item!',
description: 'This is my item. It will be initialized with these properties.'
});
}
}
I got the Object.assign() bit from an article I read and it works really well. It allows me to create new items using data from the server, or if I want an empty Item I simply don't pass in anything.
Now I've reached a point where I need my model to have access to another class so I'm using Aurelia's Dependency Injection like this:
import {inject} from 'aurelia-framework';
import {Router} from 'aurelia-router';
#inject(Router)
export class Item {
id = null;
name = '';
description = '';
constructor (router, data) {
this.router = router;
Object.assign(this, data);
}
get permalink () {
return window.location.protocol + '//' + window.location.host + this.router.generate('item', {itemId: this.id});
}
}
Now my problem is this; how do I create a new Item() without passing in the Router myself? I guess switching the order of argument to constructor() would do the trick but that doesn't seem to work with Aurelia?
And I don't want to have to do this every time I create a new Item:
import {inject} from 'aurelia-framework';
import {Router} from 'aurelia-router';
#inject(Router)
export class SomeViewModel {
constructor (router) {
this.router = router;
}
activate () {
this.myItem = new Item(this.router, {
name: 'My Item!',
description: 'This is my item. It will be initialized with these properties.'
});
}
}
Surely there must be a better way to solve this?
Use the Factory resolver. Here's an example: https://gist.run?id=46642ac54893186067e7cd890d6722a3**
import {inject, Factory} from 'aurelia-dependency-injection';
import {MyModel} from './my-model';
#inject(Factory.of(MyModel))
export class App {
message = 'Hello World!';
constructor(createModel) {
let model = createModel('my data');
}
}
my-model.js
import {inject} from 'aurelia-dependency-injection';
import {EventAggregator} from 'aurelia-event-aggregator';
#inject(EventAggregator)
export class MyModel {
constructor(eventAggregator, data) {
console.log(eventAggregator, data);
}
}

Categories

Resources