Skip to content

Instantly share code, notes, and snippets.

@MarcelCutts
Created August 1, 2018 19:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MarcelCutts/235e94ebeacb926aec2cac569915ef06 to your computer and use it in GitHub Desktop.
Save MarcelCutts/235e94ebeacb926aec2cac569915ef06 to your computer and use it in GitHub Desktop.
Incrementor with HOC
type hoc = ReasonReact.reactClass => ReasonReact.reactClass;
module type CreateWithStateParams = {type state; let defaultValue: state;};
module CreateWithState = (Params: CreateWithStateParams) => {
[@bs.module "recompose"]
external withState : (string, string, Params.state) => hoc = "withState";
type setState = Params.state => unit;
type children =
(~setState: setState, ~state: Params.state) => ReasonReact.reactElement;
let component = ReasonReact.statelessComponent("WithState");
let make' = (~setState: setState, ~state: Params.state, children: children) => {
...component,
render: _self => children(~setState, ~state),
};
let jsComponent =
ReasonReact.wrapReasonForJs(
~component,
(
props: {
.
"setState": setState,
"state": Params.state,
"children": children,
},
) =>
make'(~setState=props##setState, ~state=props##state, props##children)
);
let enhanced =
withState("state", "setState", Params.defaultValue, jsComponent);
let make = (children: children) =>
ReasonReact.wrapJsForReason(
~reactClass=enhanced,
~props=Js.Obj.empty(),
children,
);
};
module WithCountState =
CreateWithState({
type state = int;
let defaultValue = 0;
});
let component = ReasonReact.statelessComponent("WithStateRecompose");
let make = _children => {
...component,
render: _self =>
<WithCountState>
...(
(~setState, ~state as count) =>
<div>
("Count: " ++ string_of_int(count) |> ReasonReact.string)
<button onClick=(_ => setState(5))>
("Incr" |> ReasonReact.string)
</button>
</div>
)
</WithCountState>,
};
@fakenickels
Copy link

type hoc = ReasonReact.reactClass => ReasonReact.reactClass;

module type CreateWithStateParams = {type state; let defaultValue: state;};

module CreateWithState = (Params: CreateWithStateParams) => {
  [@bs.module "recompose"]
  external withState : (string, string, Params.state) => hoc = "withState";
  type setState = (. Params.state) => unit;

  type children =
    (~setState: setState, ~state: Params.state) => ReasonReact.reactElement;
  let component = ReasonReact.statelessComponent("WithState");
  let make' = (~setState: setState, ~state: Params.state, children: children) => {
    ...component,
    render: _self => children(~setState, ~state),
  };

  let jsComponent =
    ReasonReact.wrapReasonForJs(
      ~component,
      (
        props: {
          .
          "setState": setState,
          "state": Params.state,
          "children": children,
        },
      ) =>
      make'(~setState=props##setState, ~state=props##state, props##children)
    );
  let enhanced =
    withState("state", "setState", Params.defaultValue, jsComponent);
  let make = (children: children) =>
    ReasonReact.wrapJsForReason(
      ~reactClass=enhanced,
      ~props=Js.Obj.empty(),
      children,
    );
};

module WithCountState =
  CreateWithState({
    type state = int;
    let defaultValue = 0;
  });

let component = ReasonReact.statelessComponent("WithStateRecompose");
let make = _children => {
  ...component,
  render: _self =>
    <WithCountState>
      ...(
           (~setState, ~state as count) =>
             <div>
               ("Count: " ++ string_of_int(count) |> ReasonReact.string)
               <button onClick=(_ => setState(. 5))>
                 ("Incr" |> ReasonReact.string)
               </button>
             </div>
         )
    </WithCountState>,
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment