ReactX is a React.js extension library, add missing features form React.js
Install
Install using npm.
$ npm install reactx --save
React Compatibility
ReactX is designed to be fully backward compatible with React, which can be used as drop in replacement of React without any code change.
All neat features are included automatically.
// import React from 'react';; // No code need to be updatedComponent ...
ReactX.Component
ReactX.Component
is a ES6 style Component base class, bundled with wanted features.
; Component { return <span>ReactX Component is cool</span>; }
this.data
Immutable state ReactX componet built in some methods to make it easier to use immutable.js as state in Component
.
It follows the approach that recommended by Facebook.
To distinguish the immutable state from normal ReactX state, the new property is called data
.
{ return <span>thisdata</span>;}
CAUTION
Unlike this.state
, this.data
is not readonly, following code cause error.
thisdata = text: 'new Text';
HINT
Data and its children are immutable objects, which might not be accepted by other components or libraries. You might need to call this.data.toJS()
to convert it to normal object.
{ return <ChildComponent ...thisdata className=thisdatacssClasses />;}
Initialize data with constructor
The data can be initialized by calling super's constructor.
The value provided will be converted into immutable object automatically.
; Component { superprops text: 'Text initialized' ; } { return <span>thisdata;</span>; // renders <span>Text initialized</span> }
HINT
The second parameter is optional, this.data
will be initialized with {}
if nothing provided.
; Component { superprops; } { return <span>JSON</span>; // renders <span>{}</span> }
CAUTION
If build your own abstract component based on ReactX.Component
, make sure you constructor keep the following signature.
; Component { }
initData
Initialize data with Besides the constructor, the data can also by initialized by calling initData
method.
The value provided will be converted into immutable object automatically.
Component { superprops; } { this; } { return <span>thisdata;</span>; // renders <span>Text initialized</span> }
CAUTION
Do not swap usage of this.updateData
with this.initData
, although they behaves similar but the actually have quite different implementation. Here explains why.
Update Data
Similar to setState
, ReactX.Component
provides updateData
to manipulate data.
CAUTION
Always update data or state by updateData
or setState
methods, or you might break React's life cycle management.
// this.data = {}this; // Set a whole new value// this.data = { name: 'Tim', hobbies: ['coding', 'coding', 'coding'] }this; // Replace previous value with new one// this.data = { name: 'Suca' }this; // Quick update previous// this.data = { name: 'Suca', 'hobby', 'relics' };this;
For more available methods, check immutable.js official document.
State Link
When dealing with form inputs, React provides [State Link], but it is provides as Mixin, which isn't supported by ES6 syntax.
So ReactX.Component
provides createStateLink
to create state link.
; Component { return <div> <input type='checkbox' checkedLink=this /> <input type='text' valueLink=this </div> ; } { return thisdata; } { this; } { return thisdata; } { this; }
HINT createStateLink
binds this
for you automatically. So you don't need to worry about the this
.
Deal with value group
When deal with input group, usually it shares same change handler across inputs.
So in the handler
, it is important to know which input triggers the event.
By specify the 3rd parameter of createStateLink
to true, enable ReactX.Component
to pass property name
to callback.
; Component { return <div> <input type='checkbox' checkedLink=this /> <input type='checkbox' checkedLink=this /> <input type='checkbox' checkedLink=this /> <input type='checkbox' checkedLink=this /> </div> ; } { // featureName corresponding to the first value passed to createStateLink. this; }
Pure Render Component
Pure Render component usually means:
- Clean design
- Testability
- Performance Boost
But to make a component Pure Render isn't that easy in ES6 style syntax. So ReactX.Component
provides enablePureRender
static method.
; Component ...MyPureRenderComponent;
Under the hood, enablePureRender
method wraps up react-pure-render, make it more accessible without relaying on ES7 draft syntax and mixin.
React Router integration
Again, react-router is a popular router solution, which provides clean syntax to add routing mechanism to react app. But some of its feature heavily depends on Mixin, which is not available in ES6 syntax.
So ReactX.Component
provides enableReactRouter
utility method to solve the issue. It expose router
property to access react-router
instance.
; Component { thisrouter; }MyComponent;
HINT
If you have already declared router
property on your Component, you can ask ReactX.Component
to expose react-router
with a different property.
; Component { return thisdata; } { thisreactRouter; // Access react-router via reactRouter instead of default router }MyComponent;
MixIn
Although MixIn is not supported by ES6 syntax, and which can be replace with High Order Component. But due to a lot of existing libraries are strongly depends on Mixin. So it is import to have it.
ReactX.Component
provides includeSimpleMixIn
to enable developer mount existing mixin onto ES6 style Component with some limitation.
Simple MixIn
The major criticism on Mixin focused on it messing up the life-cycle callbacks and state/property initialization. Except that, mixin is still the most convenient way to abstract concerns.
ReactX.Component
support mixin with some tradeoff. It doesn't merge the state/property initialization automatically. It also doesn't dispatch life cycle to multiple method automatically. It leaves all these stuff to developer, enable developer to have a better control on the code.
; const SimpleMixIn = { return thisscores / thisscoreslength; } Component { return thisdata; } { return <span>this</span>; } MyComponent;
getInitialState, getDefaultProps, propTypes, contextTypes
TODO
Prefix and Lifecycle callbacks
TODO
Name Conflict
TODO
ReactX.PropertyBinder
In Flux architecture application, to consume Store
data in Component
isn't a straightforward as it sounds. Different Flux Implementations provides different approaches.
When you try to apply these solutions, you might quickly find:
- They require modifications to my Component
- They depend on MixIns, which is not supported by ES6 style Component
- They creates wrapper class
- The connection between Component and Store are hidden
- They add additional dependencies to my Component
- They add external state to my Component, which makes it not a Pure Render any more.
- They make my Component hard to test
- They make my Component hard to reuse
- They just don't feel right to me!
If you feel disappointed about the solutions, PropertyBinder
might be what you're looking for.
Property Binding
Suppose I have a RoleList
component that renders a list of roles, and which is a pure render component.
So I can easily using React Dev Tools play with it.
When finished the Component, to connect it to RoleConfigStore
, it can be done as following code describes
It bounds RoleConfigStore
state to RoleList's property lists. And the binding relation can be express in HTML syntax.
When RoleConfigStore
updated, the RoleList proper will updated correspondingly.
Binding to all kind of sources
PropertyBinder
doesn't require the type of source, theoretically it works with all kind of source/stores. It even works with plain objects without auto-refresh.
PropertyBindiner
will try to hook addChangeListener
on object on source, but this behavior can be overrode by specify listenerHook
on PropertyBinder
.
// Bound to RoleConfigStore with listenTo method
// Disable Property Update, and bind to plain object
Bind to multiple source
PropertyBinder
also support multiple sources, when you specify multiSource
// Previous code applies following binding to ControlPanel
License
MIT