reductive-dev-tools
reductive and reason-react reducer component integration with Redux DevTools.
Installation
via npm:
npm install --save-dev reductive-dev-tools
Caveats
- Add
-bs-g
into "bsc-flags"
of your bsconfig.json to have variant and record field names available inside extension.
- Prefer variants with associated data to plain (
SomeAction(unit)
to SomeAction
) since plain varaints do no carry debug metedata with them (represented as numbers in js)
Supported DevTools Features
Usage with Reductive
Utilize provided store enhancer ReductiveDevTools.Connectors.reductiveEnhancer
let storeEnhancer =
ReductiveDevTools.(
Connectors.reductiveEnhancer(
Extension.enhancerOptions(~name="MyApp", ()),
)
);
let storeCreator = storeEnhancer @@ Reductive.Store.create;
Experimental: Direct Usage with ReasonReact reducer component
-
Create devtools connection with ReductiveDevTools.Connectors.register()
.
/* in your component */
didMount: self =>
ReductiveDevTools.Connectors.register(
~connectionId,
~component=self,
~options=ReductiveDevTools.Extension.enhancerOptions(
~actionCreators=Js.Dict.fromList([
("click", (.) => `Click()),
("toogle", (.) => `Toggle(()))
]),
()),
()),
-
Retain an action... inside your component state... (yeah...)
/* State declaration */
type state = {
count: int,
show: bool,
preserved: preservedAction
} and preservedAction = {
action: option([`Click(unit) | `Toggle(unit) | `DevToolStateUpdate(state)])
};
/* your reducer */
reducer: (action, state) => {
let stateWithAction = {...state, preserved: { action: Some(action) }};
switch (action) {
| `Click(_) => ReasonReact.Update({...stateWithAction, count: state.count + 1})
| `Toggle(_) => ReasonReact.Update({...stateWithAction, show: !state.show})
| `DevToolStateUpdate(devToolsState) => ReasonReact.Update({...devToolsState, preserved: { action: Some(action) }})
}
},
-
Send new state and action with ReductiveDevTools.Connectors.send()
/* in your component */
willUpdate: ({newSelf}) =>
switch(newSelf.state.preserved.action){
| Some(action) => ReductiveDevTools.Connectors.send(~connectionId, ~action, ~state=newSelf.state);
| None => ()
},
-
Handle actions dispatched from the monitor (DevToolStateUpdate('state)
)
/* your reducer */
reducer: (action, state) => {
let stateWithAction = {...state, preserved: { action: Some(action) }};
switch (action) {
/* other actions */
| `DevToolStateUpdate(devToolsState) => ReasonReact.Update({...devToolsState, preserved: { action: Some(action) }})
}
},
-
Unsubscribe when needed with ReductiveDevTools.Connectors.unsubscribe(~connectionId)
Options
ReductiveDevTools.Extension.enhancerOptions(
/* the instance name to be showed on the monitor page */
~name="SomeTest",
/* action creators functions to be available in the Dispatcher. */
~actionCreators=Js.Dict.fromList([
("increment", (.) => CounterAction(Increment)),
("decrement", (.) => CounterAction(Decrement)),
("complexAppend", ((first, last) => StringAction(ComplexAppend(first, last))) |> Obj.magic)
]),
/* if more than one action is dispatched in the indicated interval, all new actions will be collected and sent at once */
~latency=500,
/* maximum allowed actions to be stored in the history tree. */
~maxAge=50,
/* actions types to be hidden / shown in the monitors (while passed to the reducers), If `actionsWhitelist` specified, `actionsBlacklist` is ignored. */
~actionsBlacklist=[|"StringAction"|],
/* actions types to be hidden / shown in the monitors (while passed to the reducers), If `actionsWhitelist` specified, `actionsBlacklist` is ignored. */
~actionsWhitelist=[|"CounterAction"|],
/* if specified as `true`, whenever there's an exception in reducers, the monitors will show the error message, and next actions will not be dispatched. */
~shouldCatchErrors=false,
/* If you want to restrict the extension, specify the features you allow. */
~features=ReductiveDevTools.Extension.enhancerFeatures(
~pause=true,
~persist=true,
~export=true,
~import=Obj.magic("custom"),
~jump=true,
~dispatch=true,
()),
())
Word Of Caution
Current implementation depends on internal bucklescript representation of debug metadata and variants in js. Changes to it in future may silently break the extension.