DumbRelay ![npm version](https://badge.fury.io/js/dumb-relay.svg)
Link your data to React.js components with fun & pleasure!
Installation
$ npm install dumb-relay
Quick Guide
Say you have a React.js component and a data-providing API. If you want to access the data from inside of the component, you do the following:
class MyList extends Component {
render() {
var clients = [];
api.getClients((res) => {
clients = res.data.results;
this.forceUpdate(); // Render the component again.
}
});
var list = clients.map(function (client) {
return (<li>{client.name}</li>);
};
return(<ul>{list}</ul>);
}
}
With DumbRelay, you can do it more beautiful way:
import DumbRelay from 'dumb-relay';
class MyList extends Component {
render() {
var clients = this._data['clients'],
list = clients.map(function (client) {
return (<li>{client.name}</li>);
};
return(<ul>{list}</ul>);
}
}
DumbRelay.link(MyList, {
clients: api.getClients
});
The function api.getClients
takes one object as an argument. That object contains:
success
- a callback to be called with an object containing the dataerror
- a callback to be called in case of errordata
- optional; an object with query parameters, or a function returning such an object
Also, you can add some magic:
DumbRelay.link(MyList, {
clients: {
source: api.getClients,
// If you want to get actual data every 5 seconds.
rate: 5000,
// You can pipe the data through some filters/maps/whatever.
pipe: [
function (data, callback) {
// Let's show only VIP clients.
data = data.filter((client) => client.isVIP());
}
]
}
});
API Reference
Linking
After linking, several names become occupied in React component scope: _data
, _dataRenew
, _bindings
and _bindingsScope
. If you want to change those names, you must use dataPropertyName
and bindingsPropertyName
(better you use DumbRelay.setup()
for that purpose).
DumbRelay.link()
method has three arguments:
Component
is a class of a React componentbindings
is a list of objects/functions which describe the way data is getting into a componentdefaults
is an object with default options for all the bindings
for a given component
The list of properties in each bindings
object is:
source
function source
is a source of data. It can be placed only in bindings
, not in defaults
nor via DumbRelay.setup()
.
DumbRelay.link(Component, {
clients: {
source: API.getClients
}
});
You can also declare that function right to the name of a binding, if you have no additional options:
DumbRelay.link(Component, {
clients: API.getClients
});
function extractor
is a tool to extract data that is nested. It receives two args: data
and callback
. As well as every function in pipe
array, it must provide callback
with null
and refined data
, like so:
DumbRelay.link(Component, {
clients: {
source: API.getClients,
extractor: function (data, callback) {
data = data.someObj.nestedData;
callback(null, data);
}
}
});
pipe
array pipe
is an array of functions. Their usage is similar to that of extractor
. Data flows through the pipe
in the direct order. You must pass null
as the first argument, like in most of async library functions.
DumbRelay.link(Component, {
clients: {
source: API.getClients,
pipe: [
function (data, callback) {
callback(null, data.map(function (item) {
return {
date: toBeautifulString(item.date)
}
});
},
function (data, callback) {
callback(null, data.map(function (item) {
return {
date: backToUglyView(item.date)
};
});
}
]
}
});
rate
number rate
is a renewal rate for a given binding, in milliseconds.
data
object data
is an object that may be interpreted, for example, as a query string for a URI. data
may also be a function that returns such an object.
dataPropertyName
string dataPropertyName
is a replacement for 'data' in _data
and _dataRenew
properties in prototype
of your component. By default it is:
/* React component code */
render() {
var clients = this._data.clients;
// XML parsing here
}
and it can be:
/* React component code */
render() {
var clients = this.myDataName.clients;
// XML parsing here
}
or whatever you like.
bindingsPropertyName
string bindingsPropertyName
is a replacement for 'bindings' in _bindings
and _bindingsScope
properties in prototype
of your component. It is very innermost of the DumbRelay and is used like dataPropertyName
though you don't have to encounter it directly in most cases.
Setup
DumbRelay.setup()
method takes one object as an argument, containing all the properties listed above (except for source
) and sets them as global defaults for the entire app.
Manual data renewal
As well as DumbRelay provides a way for automatic data renewal (see rate
), there is a method in your component prototype
called _dataRenew()
which may be used from inside of event handlers or whatever. It is given with any number of binding names. For example:
class YourComponent extends Component {
_customClickHandler() {
this._dataRenew('dataField');
}
render() {
return(
<div>
<div>{this._data.dataField}</div>
<button onClick={this._customClickHandler.bind(this)}>Click me!</button>
</div>
);
}
}
DumbRelay(YourComponent, {
dataField: API.getData
});
API Usage Example
DumbRelay.link(Component, {
source: API.getClients,
// It will do its work before pipe functions.
extractor: function (data, callback) {
data = data.someObj.nestedData;
callback(null, data);
},
pipe: [
someFilter, // That will be first
anotherOne // And that will be second
],
rate: 5000, // 5 seconds
// Consider it will be a query, like '?min=25&max=55'
data: {
min: 25,
max: 55
}
});
Useful Patterns
You can use extractor for each binding of a component with extractor
in defaults
:
DumbRelay.link(Component, {
clients: API.getClients,
companies: API.getCompanies
},
{
extractor: function (rawData, callback) {
var data = rawData.data.results;
callback(null, data);
}
});
or even for the whole application using DumbRelay.setup()
:
DumbRelay.setup({
extractor: function (rawData, callback) {
var data = rawData.data.results;
callback(null, data);
}
});