Using React Central State to Simplify Your App
Eduardo Gomes
Posted on January 6, 2019
React-central-state is an easy-to-use React library created to help you share a common state between your components without passing state to props and minimizing re-rendering. It is available on npm and github.
If you do not want to deal with redux/mobx complexity, or your application is just not that big to justify these tools, I propose a different and simpler approach:
import React from 'react';
import {CSComponent} from 'react-central-state';
class _Component1 extends React.Component {
...
changeFoo(value){
this.setCentralState({foo:value});
}
...
}
class _Component2 extends React.Component {
...
updateWith(){
return ['foo','someOtherProperty','anotherOne'];
}
render(){
let foo = this.centralState.foo || "Nothing here";
return <div>{foo}</div>
}
}
export const Component1 = CSComponent(_Component1);
export const Component2 = CSComponent(_Component2);
Why Use It
Easy to use, requiring almost no additional code.
The syntax is very similar to vanilla react state management.
It allows all components to read and update from one central state.
You can use it along with react’s normal state.
Gives you control of what triggers your components to update.
Only causes re-rendering when you need it.
When the State Changes…
Each component only subscribes to the central state properties changes it is interested in.
Components are notified by mounting order.
shouldComponentUpdate method has nextCentralState injected as third parameter, returning false will avoid a re-render — a.k.a. the default behavior.
How It Works
The store keeps information about the CSComponents mounting order. When a change occurs to its state, updates are dispatched orderly trough components that are observing at least one of the changed properties.
While redux does this by mapping relevant “sub-state” trough each component props, central state asks you to declare all properties that, when changed, require re-rendering.
This orderly dispatching also avoids duplicate render calls caused by either an owner component making children re-render, or changes in state inside callbacks.
The Downside
Accessing a central state property in render() that is not returned by updateWith() may lead to “dirty” DOM elements — i.e., not synced with the application state.
On the other hand, returning property keys from updateWith() that are not accessed in render() will most likely cause useless re-rendering.
In the end, you just need to pay attention to what properties render needs to keep up with.
How to use it
You’ll only need to make 2 adjustments to your code:
Wrap your exported components with CSComponent
Implement updateWith() on wrapped components method and return an array of central state properties that notify the component to update when changing value.
Updating and Reading from the central state:
Pretty much like in vanilla react, use this.setCentralState() to update and read from this.centralState property.
You can also register functions to be called when one or more properties change, right before react components are re-rendered:
import React from 'react';
import {CSComponent} from 'react-central-state';
class Display extends React.Component {
constructor(props){
super(props);
//Register listener for 'foo' object changes
this.fooListener = this.addCentralStateListener(prevstate=>{
alert("Foo changing from "+prevstate.foo+" to "+this.centralState.foo);
},'foo');
}
//Dont forget to remove the listener on unmounting
componentWillUnmount(){
this.removeCentralStateListener(this.fooListener);
}
updateWith(){return ['foo']};
//Re-render occurs after this.fooListener is called.
render(){
return <div>{this.centralState.foo}</div>
}
}
export default CSComponent(Display);
Next Steps
- Do some kind of batching on updates when done from the same callback/event handler.
That’s it, if you feel like the pros outweigh the cons I listed here, go ahead and give it a try.
Also, I’ll be glad to know what you think and if you find any problems/bugs please report them on github.
Posted on January 6, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.