Skip to content

MargaretKrutikova/reason-react-elmish

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

reason-react-elmish

The library implements the "model-update" part of the "model-view-update" elm architecture, leveraging React as the "view" part and implementing the missing part of state and effect management.

🚧 Not production ready (yet), but trying out is highly encouraged 🚧

Installation

Can be installed via:

npm install --save "https://github.com/MargaretKrutikova/reason-react-elmish"

and added to bsconfig.json:

"bs-dependencies": [
  "reason-react-elmish"
]

Peer dependencies are react, reason-react and bs-platform.

Example usage

First, define your types for message and model, implement the update function and effectful functions (if any).

// AppModel.re
type message =
  | FetchUsersRequest
  | FetchUsersSuccess(userApiResponse)
  | FetchUsersError;

type data =
  | NotAsked
  | Loading
  | Error
  | Success(userApiResponse);

type model = {data};

let fetchUsers = dispatch => {
  Js.Promise.(
    Caller.fetchUsers()
    |> then_(response => dispatch(FetchUsersSuccess(response)) |> resolve)
    |> catch(_ => dispatch(FetchUsersError) |> resolve)
  )
  |> ignore;
  None;
};

let update = (_, message) => {
  switch (message) {
  | FetchUsersRequest => ({data: Loading}, Some(fetchUsers))
  | FetchUsersSuccess(data) => ({data: Success(data)}, None)
  | FetchUsersError => ({data: Error}, None)
  };
};

let initModel = ({data: NotAsked}, None);

Setup your elmish store with all of the above and your initial model with initial effect (if any).

// AppStore.re
include Elmish.Make({
  type model = AppModel.model;
  type message = AppModel.message;

  let update = AppModel.update;
  let storeEnhancer = None;
  let initialModel = AppModel.initModel;
});

See example file ./examples/AppModel.re and ./examples/AppStore.re.

Then hook in your store into the react component tree somewhere at the root:

// Index.re
ReactDOMRe.renderToElementWithId(
  <AppStore.ElmishProvider> <Root /> </AppStore.ElmishProvider>,
  "root",
);

and use the hooks to get access to the model and dispatch in your components:

let selector = (model: AppModel.model) => model.data;

[@react.component]
let make = () => {
  let dispatch = AppStore.useDispatch();
  let result = AppStore.useSelector(selector);

  <div>
    <button onClick={_event => dispatch(FetchUsersRequest)}>
      {React.string("Fetch users")}
    </button>
  </div>;
};

Run examples

npm install
npm start
# in another tab
npm run watch:bs

About

The Elm Architecture for reason-react

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages