Skip to content

Dead simple shared state in Reason React with a redux-like interface.

License

Notifications You must be signed in to change notification settings

sikanhe/reason-atomic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Atomic npm version

Dead simple shared state in Reason React with a redux-like interface.

Installation

yarn add reason-atomic

Then add reason-atomic to your bs-dependencies in bsconfig.json

{
  ...
  "bs-dependencies": ["reason-atomic"]
}

Usage

Configure your state by creating a module with state, getInitialState, action, and reducer.

module Config = {
  type state = {count: int};

  let getInitialState = () => {count: 0};

  type action =
    | Increment
    | Decrement
    | NoChange;

  let reducer = state =>
    fun
    | Increment => {count: state.count + 1}
    | Decrement => {count: state.count - 1}
    | NoChange => state;

}; 

Create a new state module with the config

module AppState = Atomic.Make(Config);
// module AppState2 = Atomic.Make(Config);
// module AppState3 = Atomic.Make(Config);

// Create as many instances as you like..

Access the state as a hook, and dispatch actions

[@react.component]
let make = () => {
  let state = AppState.useState();

  <div>
    {React.string("global count: " ++ string_of_int(state.count))}
    <button onClick={_ => AppState.dispatch(Increment)}> {React.string("+")} </button>
    <button onClick={_ => AppState.dispatch(Decrement)}> {React.string("-")} </button>
  </div>;
};

If you only care about a subset of the state, you can use useMappedState. This also means that the component with the hook won't re-render unless the state it cares about changes - avoiding excessive re-rendering.

[@react.component]
let make = () => {
  let count = AppState.useMappedState(state => state.count);

  <div>
    {React.string("global count: " ++ string_of_int(count))}
  </div>;
};

You can also use the render-props pattern to consume the state as well, using the Consumer component and pass the mapper prop.

[@react.component]
let make = () => {
  <AppState.Consumer mapper={state => state.count}>
    {count => React.string("global count: " ++ string_of_int(count))}
  </AppState.Consumer>;
};

About

Dead simple shared state in Reason React with a redux-like interface.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages