React native- Best way to create singleton pattern - reactjs

I am new in react-native coding but have experienced on objective-c and swift coding and want use singleton pattern in react-native.
I have tried to find out the solution from other StackOverflow answer but most of them are creating only singleton functions as below code:
var Singleton = (function () {
var instance;
function createInstance() {
var object = new Object("I am the instance");
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
function run() {
var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();
alert("Same instance? " + (instance1 === instance2));
}
As we can see in above code here we are creating singleton function not class.
Please let me know if any way to create singleton class and pass multiple variables in that class as objective-c or swift.
Note: Please also notify me if I am going in the wrong direction.

Here's my implementation for singleton class...
Controller.js
export default class Controller {
static instance = Controller.instance || new Controller()
helloWorld() {
console.log("Hello World... \(^_^)/ !!")
}
}
Usage:
import Controller from 'Controller.js'
Controller.instance.helloWorld()

You can use something like that
class SingletonClass {
static instance = null;
static createInstance() {
var object = new SingletonClass();
return object;
}
static getInstance () {
if (!SingletonClass.instance) {
SingletonClass.instance = SingletonClass.createInstance();
}
return SingletonClass.instance;
}
}
var instance1 = SingletonClass.getInstance();
var instance2 = SingletonClass.getInstance();

The singleton pattern isn't used much in the JS ecosystem. What you should look into is http://mobx.js.org. MobX is a library that allows you to create observable objects to store data for your apps. You instantiate one store for each domain you please and make edits to that store to change app state.

Related

Data Acces Objects Factory Design Pattern in React?

I'm currently going through some tutorial about React Design Patterns, subject: Custom Hooks.
While the concept feels awesome and seems familiar to me, the solution below provided by the tutor made me question how to deal with different data sources.
Is there something like the above mentioned DAO Factory Pattern, you can find in Frameworks like J2E?
Or how is the common approach to handle this challenges in React to make the code maintainable?
My first intension woulda be throwing the stuff into a Factory Component and having implementations for the specific providers, basically like it is shown in the two other Code snippets bewlow.
Is this the regular wayt to do it?
Any help, tips, additional sources to learn this would be highly appreciated.
Here's the solution, with the both possible implementations thrown into the React Form Component:
import axios from 'axios';
import { useDataSource } from './useDataSource';
import { useResource } from './useResource';
import { useUser } from './useUser';
const serverResource = resourceUrl => async () => {
const response = await axios.get(resourceUrl);
return response.data;
};
const localStorageResource = key => () => {
return localStorage.getItem(key);
}
export const UserInfo = ({ userId }) => {
// const user = useResource(`/users/${userId}`);
const user = useDataSource(serverResource(`/users/${userId}`));
const message = useDataSource(localStorageResource('message'));
const { name, age, hairColor, hobbies } = user || {};
return user ? (
<>
<h3>{name}</h3>
<p>Age: {age} years</p>
<p>Hair Color: {hairColor}</p>
<h3>Hobbies:</h3>
<ul>
{hobbies.map(hobby => <li key={hobby}>{hobby}</li>)}
</ul>
</>
) : <p>Loading...</p>;
}
And here's the DAO Factory Pattern example provided by Oracle:
src: https://www.oracle.com/java/technologies/dataaccessobject.html
// Abstract class DAO Factory
public abstract class DAOFactory {
// List of DAO types supported by the factory
public static final int CLOUDSCAPE = 1;
public static final int ORACLE = 2;
public static final int SYBASE = 3;
...
// There will be a method for each DAO that can be
// created. The concrete factories will have to
// implement these methods.
public abstract CustomerDAO getCustomerDAO();
public abstract AccountDAO getAccountDAO();
public abstract OrderDAO getOrderDAO();
...
public static DAOFactory getDAOFactory(
int whichFactory) {
switch (whichFactory) {
case CLOUDSCAPE:
return new CloudscapeDAOFactory();
case ORACLE :
return new OracleDAOFactory();
case SYBASE :
return new SybaseDAOFactory();
...
default :
return null;
}
}
}
...with a concrete implementation:
// Cloudscape concrete DAO Factory implementation
import java.sql.*;
public class CloudscapeDAOFactory extends DAOFactory {
public static final String DRIVER=
"COM.cloudscape.core.RmiJdbcDriver";
public static final String DBURL=
"jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB";
// method to create Cloudscape connections
public static Connection createConnection() {
// Use DRIVER and DBURL to create a connection
// Recommend connection pool implementation/usage
}
public CustomerDAO getCustomerDAO() {
// CloudscapeCustomerDAO implements CustomerDAO
return new CloudscapeCustomerDAO();
}
public AccountDAO getAccountDAO() {
// CloudscapeAccountDAO implements AccountDAO
return new CloudscapeAccountDAO();
}
public OrderDAO getOrderDAO() {
// CloudscapeOrderDAO implements OrderDAO
return new CloudscapeOrderDAO();
}
...
}
how is the common approach to handle this challenges in React to make the code maintainable?
sure you can. As design patterns do not depend on programming language.
If you are using TypeScript, then you can use Abstract class
If you are using plain JavaScript, then you can use the following approach
An example of using Factory in React can be seen here.

How do I use the factory pattern if I'm migrating from Angular 1.5.8 to Angular 2?

If I'm migrating to Angular 2 and I want to use the factory pattern to create a transient dependency (a dependency that doesn't share state between components in which it gets injected), what is the best way to register a service in angular 1.5.8 with plans to migrate to ng2's way of registering services
I know in angular 2, components can reinstantiate services by passing them to the providers array, but that option doesn't exist in angular 1, and it seems like .factory is all but deprecated in angular 2 since the docs don't give it much love
An example would be a TabulationService that manages the state of which tab a user is viewing on a dashboard, which would obviously not share state between components. I would want to reinstantiate the service in each component it gets injected into. But I also want to avoid using .factory if Angular 2 best practices seem to shy away from using it.
Here is the "hack" I've resorted to, but I don't like it because even though it gets me type hinting and statelessness for my service, I can't use dependency injection in the object that gets created and i have to manage the state of my service when it gets injected and when the component in which it gets injected is destroyed (by manually clearing the service's state):
tab-manager.service.ts:
import { TabManager } from './tab-manager.class';
export class TabService {
manager;
public initialize(tabs: string[], defaultTab: string) {
this.manager = new TabManager(tabs, defaultTab);
}
}
tab-manager.class.ts:
import { includes } from 'lodash';
const mandatory = (param) => { throw new Error(`${ param } is a required field in Tab Manager!`) };
export class TabManager {
tab: string;
constructor(public tabs: string[] = mandatory(`tabs`), public defaultTab: string = mandatory('defaultTab')) {
this.checkTab(defaultTab);
this.tab = defaultTab;
}
public switchTab(tab) {
const self = this;
self.checkTab(tab);
self.tab = tab;
}
private checkTab(tab: string) {
const self = this;
if (!includes(self.tabs, tab)) {
throw new Error(`{ tab } is not a valid tab. Available tabs are ${ self.tabs.join(',') }`);
}
}
}
The service then gets initialized by importing the TabManager service from tab-manager.service.ts and calling `angular.service('TabService', TabManagerService)
There's nothing to blame Angular 2 documentation on. Angular 1 factory service is implemented in Angular 2 DI as useFactory provider.
It doesn't really matter here if it is factory or service in this case. Both serve the same purpose and share the same behaviour - they are singletons in Angular 1. Similarly, useFactory and useClass providers are singletons within the same injector in Angular 2.
To achieve the desired behaviour uniformly in both frameworks a dependency should be instantiated after injection. It doesn't really matter if this is done with factory or constructor function - they should be defined as value service in Angular 1 or useValue provider in Angular 2.
For Angular 1 it will be:
export class TabulationService { ... }
export type TTabulationService = typeof TabulationService;
...
app.value('TabulationService', TabulationService);
app.component('some', {
controller: class {
tabulationService: TabulationService;
static $inject = ['TabulationService'];
constructor (TabulationService: TTabulationService) {
this.tabulationService = new TabulationService();
}
}
});
And for Angular 2:
providers: [{ provide: TabulationService, useValue: TabulationService }]
...
#Component(...)
export class SomeComponent {
tabulationService: TabulationService;
constructor (#Inject(TabulationService) TabulationService: TTabulationService) {
this.tabulationService = new TabulationService();
}
}

Sharing data between controllers in Typescript | Angular JS

I have worked with angular js with javascript where as I know I can able to create service to share data . I am new to typescript it would be great if anyone could help us to understand how to create service in typescript to share data between controllers
The below sample service is called from the controller. Even I changed the service values when I tried redirect from other page the value is not getting changed it is having the default values. Though I am using the syntax
angular.module("app").service(...)
I believe the service is creating new instance when the controller is loaded.
export class sharedData {
public getMyProperty(): boolean {
return this._myProperty;
}
public setMyProperty(value) {
this._myProperty= value;
}
private _myProperty: boolean = false;
}
angular.module("app")
.service("sharedData", App.RfiDetail.sharedData);
I have tried with function also , but its not working
export function sharedFactory() {
return {
setStatus: setStatus,
getSuccess: getSuccess
};
function setStatus(value) {
this._myProperty = value;
}
function getSuccess() {
return this._myProperty;
}
}
angular.module(App.Constants.Modules.app)
.factory("sharedFactory", App.RfiDetail.sharedFactory);

Register Specific Module Constructor

I would like to inject different strings into each of my module's contructors. I register a factory method which constructs the module. I can then call container.Resolve<T>() and all is well. For some reason though when Nancy tries to resolve my module it throws the error
Nancy.TinyIoc.TinyIoCResolutionException: Unable to resolve type:
Plugin.HomeModule ---> Nancy.TinyIoc.TinyIoCResolutionException:
Unable to resolve type: System.String
public class HomeModule : NancyModule
{
public HomeModule(string text)
{
}
}
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
container.Register<HomeModule>((ctr, param) => { return new HomeModule("text"); });
HomeModule module = container.Resolve<HomeModule>();
}
I have also tried doing the registration in ConfigureRequestContainer() with the same results. I have tried container.Register<HomeModule>(new HomeModule("some text")); as well as AsSingleton(). I can register an implementation to the string type with container.Register<string>("text"), but this would inject the same string into all modules.
How can I register a module constructor so that Nancy can resolve it?
Modules are obtained through the INancyModuleCatalog, which is normally implemented by the bootstrapper, you'd have to create a custom variation of that - if you're using the default bootstrapper then this is the current implementation:
https://github.com/NancyFx/Nancy/blob/master/src/Nancy/DefaultNancyBootstrapper.cs#L205
The best approach for this would be to not pass in a primitive into your module, but us something richer, or perhaps a factory. The container can resolve those dependencies. Passing a plain string into the module is a sign of a problem somewhere else and a hint that your architecture probably needs rethinking
I have implemented a custom catalog that registeres only Modules of a specific namespace, but I don't know where to register this.
public CustomModuleCatalog()
{
// The license type is read from db in Global.ascx.
// So I want to register a module based on a namespace.
// The namespace is the same like the license name.
if(WebApiApplication.LicenseType == LicenseType.RouteOne)
{
var assemblyTypes = Assembly.GetExecutingAssembly().GetTypes();
var modules = assemblyTypes.Where(t => t.Namespace != null && t.Namespace.EndsWith("MyCustomNamespace"));
var nancy = modules.Where(t => t.IsAssignableFrom(typeof(INancyModule)));
foreach (var type in nancy)
{
var nancyType = (INancyModule)type;
_modules.Add(type, (INancyModule)Activator.CreateInstance(type));
}
}
}
public IEnumerable<INancyModule> GetAllModules(NancyContext context)
{
return _modules?.Values;
}
public INancyModule GetModule(Type moduleType, NancyContext context)
{
if (_modules != null && _modules.ContainsKey(moduleType))
{
return _modules[moduleType];
}
return null;
}

How can I define an AngularJS service using a TypeScript class that doesn't pollute the global scope?

I am using AngularJS and TypeScript. I want to implement an AngularJS service using a Typescript class, like this:
class HelloService {
public getWelcomeMessage():String {
return "Hello";
}
}
angular.module('app.services.helloService', []).factory('helloService', () => {
return new HelloService();
});
This compiles to the following javascript code:
var HelloService = (function () {
function HelloService() {
}
HelloService.prototype.getWelcomeMessage = function () {
return "Hello";
};
return HelloService;
})();
angular.module('app.services.helloService', []).factory('helloService', function () {
return new HelloService();
});
This pollutes the global namespace with the variable HelloService, which I obviously don't want. (Using Chrome's console I verified that HelloService was an object.) How can I solve/avoid this problem?
I tried the obvious:
angular.module('app.services.helloService', []).factory('helloService', function () {
class HelloService { ...}
return new HelloService();
});
but that gives me a compile error ("Unexpected token; 'statement' expected.").
One possible solution I can think of is using TypeScript's import and export somehow, which in turn will use RequireJS. This probably will wrap the HelloService within a define function, thus avoiding pollution of the global scope with HelloService. However, I don't want to use RequireJS in my AngularJS application for now, as I think AngularJS is good enough for my use, and it adds complexity.
So, my question is, how can I define an AngularJS service using a TypeScript class that doesn't pollute the global scope?
2016-05-06: New example using ES6-style modules
The static $inject array and constructor remain unchanged from the previous example.
The only change is to split the classes into multiple files and use ES6 modules to pull in the class definitions.
/lib/HelloService.ts:
export class HelloService {
public getWelcomeMessage():String {
return "Hello from HelloService";
}
}
/lib/AnotherService.ts:
import {HelloService} from './HelloService';
/**
* Service that depends on HelloService.
*/
export class AnotherService {
// Define `HelloService` as a dependency.
static $inject = ['HelloService'];
constructor(
// Add the parameter and type definition.
public HelloService: HelloService
){}
public getWelcomeMessage():String {
// Access the service as: `this.HelloService`
// Enjoy auto-completion and type safety :)
var helloMsg = this.HelloService.getWelcomeMessage();
return "Welcome from AnotherService, " + helloMsg;
}
}
/index.ts:
// Using the services.
import {HelloService} from './lib/HelloService';
import {AnotherService} from './lib/AnotherService';
angular.module('HelloApp', [])
.service('HelloService', HelloService)
.service('AnotherService', AnotherService)
.run(['AnotherService', function(AnotherService: AnotherService){
console.log(AnotherService.getWelcomeMessage());
}]);
Previous answer: using namespaces
Building from Steve Fenton's answer:
To allow dependency injection, add a static $inject array on your class.
See the Angular $injector documentation on how the $inject array works.
The dependencies will be injected into your constructor in the order given by the array (and makes it work with minification).
Dependency Injection Example:
namespace MyModule {
/**
* Angular Service
*/
export class HelloService {
public getWelcomeMessage():String {
return "Hello from HelloService";
}
}
/**
* Service that depends on HelloService.
*/
export class AnotherService {
// Define `HelloService` as a dependency.
static $inject = ['HelloService'];
constructor(
// Add the parameter and type definition.
public HelloService: MyModule.HelloService
){}
public getWelcomeMessage():String {
// Access the service as: `this.HelloService`
// Enjoy auto-completion and type safety :)
var helloMsg = this.HelloService.getWelcomeMessage();
return "Welcome from AnotherService, " + helloMsg;
}
}
}
// Using the services.
angular.module('app.services.helloService', [])
.service('HelloService', MyModule.HelloService)
.service('AnotherService', MyModule.AnotherService)
.run(['AnotherService', function(AnotherService: MyModule.AnotherService){
console.log(AnotherService.getWelcomeMessage());
}]);
I should provide what I actually ended doing:
module MyModule {
export class HelloService {
public getWelcomeMessage():String {
return "Hello";
}
}
angular.module('app.services.helloService', []).factory('helloService', () => {
return new HelloService();
});
}
In this way I can use
return new HelloService();
instead of
return new MyModule.HelloService();
I have two solutions, the first gives you class-based syntax, the second leaves absolutely nothing in the global scope...
You could compromise slightly by only adding a single handle to the global scope (this really applies if you have multiple classes that you want to avoid placing in the global scope as currently you only have one class).
The following code leaves only the module in the global scope.
module MyModule {
export class HelloService {
public getWelcomeMessage():String {
return "Hello";
}
}
export class AnotherService {
public getWelcomeMessage():String {
return "Hello";
}
}
}
angular.module('app.services.helloService', []).factory('helloService', () => {
return new MyModule.HelloService();
});
angular.module('app.services.anotherService', []).factory('anotherService', () => {
return new MyModule.AnotherService();
});
Alternatively, to leave not a single thing in global scope, you could avoid the class syntax and use "plain old JavaScript":
angular.module('app.services.helloService', []).factory('helloService', () => {
var HelloService = (function () {
function HelloService() {
}
HelloService.prototype.getWelcomeMessage = function () {
return "Hello";
};
return HelloService;
})();
return new HelloService();
});
This is the method that I'm following:
module HelperServices {
export class helloService {
sayHelloWorld: () => string;
constructor() {
this.sayHelloWorld = () => {
return "Hello World";
}
}
}
}
As simple as that..

Resources