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 ๐ง
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
.
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>;
};
npm install
npm start
# in another tab
npm run watch:bs