Simple application-level state management for React apps.
As far as state management solutions go, Redux is already simple. At least, that's the idea. The reality is that while action creators, actions, and reducers are simple, open-ended concepts, their implementations can become unwieldy, and often leaves us with a lot of boilerplate.
What is simple, is React's built-in component-level state management, where events trigger action functions, which
in turn call setState, to update that component's state:
class Counter extends Component {
  constructor(props) {
      super(props);
      this.state = { value: 0 }; // initial state
      this.increment = this.increment.bind(this);
  }
  
  increment() { // action function, which calls this.setState
    this.setState(prevState => ({
        value: prevState.value + 1 // hooray, the state is updated!
    }));       
  }
  
  render() {
    return (
      <div>
        {this.state.value}
        <button onClick={this.increment}>+</button>
      </div>
    )
  }
}No reducers, no string constants, just event => action function => setState.
Redu performs this exact same flow, but at an application level, where a single StoreComponent's state acts as
your application-level state, and any of its descendant SubscriberComponents may derive props from this state, which
can include action functions to request application-level state changes.
Let's say my app looks like this:
<TopLevelComponent>
    <ChildComponent>
        <GrandChildComponent />
    </ChildComponent>
</TopLevelComponent>If the GrandChildComponent wanted to utilize props or state from the TopLevelComponent, you'd have to pass them down
first to the ChildComponent, then to the GrandChildComponent. Also, if you wanted to modify the TopLevelComponent's
state from the GrandChildComponent, you'd have to pass down an action function in the same manner, so that the
GrandChildComponent would be able to call it.
With Redu, the application-level state is stored in the StoreComponent which wraps the TopLevelComponent, and the
GrandChildComponent gets wrapped in a SubscriberComponent, which can pass down anything to the GrandChildComponent
that it needs from the StoreComponent as props:
<StoreComponent>
    <TopLevelComponent>
        <ChildComponent>
            <SubscriberComponent>
                <GrandChildComponent />
            </SubscriberComponent>
        </ChildComponent>
    </TopLevelComponent>
</StoreComponent>As a simplified illustration of how this composition works under the hood, the SubscriberComponent will render the
GrandChildComponent that it wraps, and pass down any requested application-level state, props, or action functions as props:
class SubscriberComponent extends React.Component {
    render() {
        const derivedProps = toProps(storeComponentState, storeComponentProps, storeComponentActions);
        return <GrandChildComponent {...derivedProps} {...this.props} />
    }
}npm install reduRedu is comprised of just two functions: storeOf(Component), and subscribe(Component, toProps).
Both functions take in a React.Component, and create and return wrapper components around them.
- storeOf(Component)creates and returns a- StoreComponentwrapped around the supplied- Component.- StoreComponentswrap your top-level component and manages the application-level state.
- StoreComponentsalso give you the- withInitialState(initialState)static method, which will set it's initial state, and also the- withActions(actions)static method, which will set the action functions that can modify the- StoreComponent's state.
 
- subscribe(Component, toProps)creates and returns a- SubscriberComponentwrapped around the supplied- Component.- SubscriberComponentsutilize the- StoreComponent's state, props, and action functions to create props for the supplied- Component, specified by the supplied- toPropsfunction.
 
The following is a simple color-picker, where we display a list of colors, and allow a single color to be selected.
In this example, we must pass down both an application-level state property (selectedColor),
as well as an action function (changeColor), all the way from the ColorList top-level component to the ColorOptions
grand-child components:
// app.js, the "entrypoint" of the app.
import ColorList from './components/ColorList';
const props = {
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
};
ReactDOM.render(
    React.createElement(ColorList, props),
    document.getElementById('root')
);// ColorList.jsx, displays the list of colors
import Color from './Color';
class ColorList extends React.Component {
    constructor(props) {
        super(props);
        this.state = { selectedColor: props.colors[0] };
        this.changeColor = this.changeColor.bind(this);
    }
    changeColor(color) {
        this.setState({selectedColor: color});
    }
    render() {
        return (
            <div>
                <p>
                    The selected color is {this.state.selectedColor}
                </p>
                <div>
                    {this.props.colors.map(color =>
                        <Color
                            key={color}
                            color={color}
                            changeColor={this.changeColor}
                            selectedColor={this.state.selectedColor}
                        />
                    )}
                </div>
            </div>
        );
    }
}
export default ColorList;// Color.jsx, each list item
import ColorOptions from './ColorOptions';
function Color(props) {
    return (
        <div>
            <span>This color is {props.color}</span>
            <ColorOptions
                color={props.color}
                changeColor={props.changeColor}
                selectedColor={props.selectedColor}
            />
        </div>
    );
}
export default Color;// ColorOptions.jsx, displays the relevant options for a particular color.
function ColorOptions(props) {
    return (
        <div>
            <span>Replace {props.selectedColor} with {props.color}?</span>
            <button onClick={e => props.changeColor(props.color)}>yes</button>
        </div>
    );
}
export default ColorOptions;Let's "redu" it. Our goal will be to eliminate the number of props that we need to pass down from the ColorList  to
the ColorOptions components.
To accomplish this, we will move all of the shared application-level state and action functions out of the ColorList
component and into the StoreComponent. We will then subscribe the ColorList and the ColorOptions to the
StoreComponent in order to derive what we need from it.
// app.js, where we will set up and create the StoreComponent, by wrapping the ColorList.
import { stateManagerOf } from 'redu';
import ColorList from './components/ColorList';
const props = {
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
};
const initialState = {
    selectedColor: props.colors[0]
};
const actions = {
    changeColor: function changeColor(color) {
        this.setState({
            selectedColor: color
        });
    }
};
const StoreComponent = storeOf(ColorList).withInitialState(initialState).withActions(actions);
ReactDOM.render(
    React.createElement(StoreComponent, props),
    document.getElementById('root')
);// ColorList.jsx, we are now just passing down the color to the Color component.
import { subscribe } from 'redu';
import Color from './Color';
function ColorList(props) {
    return (
        <div>
            <p>
                The selected color is {props.selectedColor}
            </p>
            <div>
                {props.colors.map(color =>
                    <Color key={color} color={color} />
                )}
            </div>
        </div>
    );
}
export default subscribe(ColorList, (storeComponentState, storeComponentProps) => {
    return {
        selectedColor: storeComponentState.selectedColor,
        colors: storeComponentProps.colors
    };
});// Color.jsx, we are no longer threading through the "selectedColor" and "changeColor" props.
import ColorOptions from './ColorOptions';
function Color(props) {
    return (
        <div>
            <span>This color is {props.color}</span>
            <ColorOptions color={props.color} />
        </div>
    );
}
export default Color;// ColorOptions.jsx, we can get the application-level state and action functions directly from the StateComponent now.
import { subscribe } from 'redu';
function ColorOptions(props) {
    return (
        <div>
            <span>Replace {props.selectedColor} with {props.color}?</span>
            <button onClick={e => props.changeColor(props.color)}>yes</button>
        </div>
    );
}
export default subscribe(ColorOptions, (storeComponentState, storeComponentProps, storeComponentActions) => {
    return {
        selectedColor: storeComponentState.selectedColor,
        changeColor: storeComponentActions.changeColor
    };
});