rservices v1.0.16
ES6 Services for React
Why I did this stuff
Recently I did some stuff with Facebooks' ReactJS. Quite soon I thought "Hey, wouldn't services be awesome" and I started to google. I found a working library, that worked for ES5 only.
Current problems with npm
When installing with NPM you will notice, that there are some error and it is not working. I have to compile the lib to ES5 to work with NPM. But due to some dependency-management, I keep getting Errors. Fork it and help me! Either you install it by downloading the lib via Github or you import the lib from the node module directly:
import {..whatever} from '(../)*node_modules/rservices/RServices'
Installation
npm install --save rservices
Usage
Import the relevant parts of RServices, depending on which you need in your current file.
import {DependencyManager, AbstractService, AbstractDIComponent} from 'path/to/RServices';
Then you can create a Service by extending the AbstractService
import {DependencyManager, AbstractService} from 'path/to/RServices';
class ExampleService extends AbstractService {
getInitialData() {
return {
foo: 1,
bar: "This value was delivered by the ExampleService."
}
}
incrementFoo() {
var foo = this.get('foo');
++foo;
this.set('foo', foo);
}
}
DependencyManager.register(ExampleService);
/**
*
* Another Example Service
*
**/
class Example2Service extends AbstractService {
getInitialData() {
return {
foo: 5,
bar: "This value was reversed by the ExampleService2 and reversed back by the filter."
}
}
doSomethingWithBar() {
var bar = this.get('bar');
bar = reverseString(bar);
this.set('bar', bar);
}
}
DependencyManager.register(Example2Service);
The getInitialData
method sets the default values of that service. incrementFoo
is a custom method.
Due to explicity the service has to be registered to the DependencyManager.
Then you write a component and extend the AbstractDIComponent
.
By adding the getComponentDependencies
method, you define which state variable should have the value of a service variable.
Then you also have the possibility to access that Service by calling this.$$services.SERVICE_NAME
.
import React from 'react';
import ReactDOM from 'react-dom';
import {AbstractDIComponent} from 'path/to/RServices';
class ExampleComponent extends AbstractDIComponent {
constructor(props) {
super(props);
this.state = {
bar: 0,
test: "test still contains its default value.",
something: ""
}
}
getComponentDependencies() {
return {
// state var bar should always have the same value as ExampleService.get('foo')
bar: [
'ExampleService',
'foo',
{
transformers: [(aNumber) => { return aNumber.toString(); }]
}
],
test: ['ExampleService', 'bar']
};
}
getPrivateComponentDependencies() {
return {
// state var bar should always have the same value as ExampleService.get('foo')
something: ['Example2Service', 'bar', {transformers: [reverseString]}]
};
}
componentDidMount() {
// access shared service
this.$$services.ExampleService.incrementFoo();
// access private service
this.$$privateServices.Example2Service.doSomethingWithBar();
}
render() {
var blockStyle = {display: 'block'};
return (
<div className="text">
<span style={blockStyle}>The value of "bar" is: {this.state.bar} ({getType(this.state.bar)})</span>
<span style={blockStyle}>The value of "test" is: {this.state.test} ({getType(this.state.test)})</span>
<span style={blockStyle}>The value of "something" is: {this.state.something} ({getType(this.state.something)})</span>
</div>
);
}
}
// DependencyManager.toggleProxyUse();
ReactDOM.render(React.createElement(ExampleComponent), document.querySelector('div'));
Use of proxies
ES6 provides the Proxy
Class. If you're up to use React Services only with Browsers,
that support proxies (ATM only Firefox), you can enable proxies by calling DependencyManager.toggleProxyUse();
before rendering your components.
That way you can access properties of a service directly:
this.$$services.ExampleService.foo++
instead of
this.$$services.ExampleService.set('foo', this.$$services.ExampleService.get('foo') + 1);
Single instances for components
If you want your components to have a non-shared Service, you can use the getPrivateComponentDependencies
Method of the AbstractDIComponent.
These services will then be stored in this.$$privateServices
.
Services without links to state variables
If you want to use services but want to access methods only or just don't want to have a services variable linked to a component state variable, you can use the following two methods:
getServices() {
return [
//'ExampleService'
];
}
getPrivateServices() {
return [];
}
Transformers
When a Servicevalue is updated, you might want to transform it somehow before passing it to the component.
E. g. your state variable should always contain a string but the value is delivered as integer, you can specify multiple transformer functions.
This is done in the getComponentDependencies
/getPrivateComponentDependencies
methods:
getComponentDependencies() {
return {
// state var bar should always have the same value as ExampleService.get('foo')
bar: [
'ExampleService',
'foo',
{
transformers: [(aNumber) => { return aNumber.toString(); }]
}
],
test: ['ExampleService', 'bar']
};
}