Skip to content

Instantly share code, notes, and snippets.

@jsiebern
Last active November 29, 2020 08:52
Show Gist options
  • Select an option

  • Save jsiebern/ac9a3ce507ad047f7c1d594446cd7b4e to your computer and use it in GitHub Desktop.

Select an option

Save jsiebern/ac9a3ce507ad047f7c1d594446cd7b4e to your computer and use it in GitHub Desktop.

Revisions

  1. jsiebern revised this gist May 2, 2019. 1 changed file with 92 additions and 84 deletions.
    176 changes: 92 additions & 84 deletions StoreAndRouterExample.re
    Original file line number Diff line number Diff line change
    @@ -1,60 +1,73 @@
    module Store = {
    type actions =
    type action =
    | Increase
    | Decrease;
    type state = {count: int};
    type store = {
    | Decrease
    | SetUsername(string);
    type state = {
    count: int,
    username: string,
    };
    type storeBag = {
    state,
    dispatch: actions => unit
    dispatch: action => unit,
    };
    let component = ReasonReact.reducerComponent("Store");
    let make = (~render, _children) => {
    ...component,
    initialState: () => {count: 0},
    reducer: (action, state) =>
    switch action {
    | Increase => ReasonReact.Update({count: state.count + 1})
    | Decrease => ReasonReact.Update({count: state.count - 1})
    },
    render: self =>
    render({state: self.state, dispatch: action => self.send(action)})
    let reducer = (state: state, action: action) =>
    switch (action) {
    | Increase => {...state, count: state.count + 1}
    | Decrease => {...state, count: state.count - 1}
    | SetUsername(username) => {...state, username}
    };

    [@react.component]
    let make = (~children: storeBag => React.element) => {
    let (state, dispatch) =
    React.useReducer(reducer, {count: 0, username: ""});

    children({state, dispatch});
    };
    };

    module Login = {
    let component = ReasonReact.statelessComponent("Login");
    let make = _children => {
    ...component,
    render: _self =>
    <div>
    <button onClick=(_event => ReasonReact.Router.push("/loggedin"))>
    (ReasonReact.stringToElement("Login"))
    </button>
    </div>
    [@react.component]
    let make = (~store: Store.storeBag) => {
    let (username, setUsername) = React.useState(() => "");

    <div>
    <input
    type_="text"
    value=username
    onChange={e => setUsername(e->ReactEvent.Form.target##value)}
    />
    <br />
    <button
    onClick={_ => {
    store.dispatch(SetUsername(username));
    ReasonReactRouter.push("#loggedin");
    }}>
    "Login"->React.string
    </button>
    </div>;
    };
    };

    module Screen = {
    let component = ReasonReact.statelessComponent("Screen");
    let make = (~store: Store.store, _children) => {
    ...component,
    render: _self =>
    <div>
    <span>
    (
    ReasonReact.stringToElement(
    "Count: " ++ string_of_int(store.state.count)
    )
    )
    </span>
    <br />
    <button onClick=(_event => store.dispatch(Increase))>
    (ReasonReact.stringToElement("Increase"))
    </button>
    <button onClick=(_event => store.dispatch(Decrease))>
    (ReasonReact.stringToElement("Decrease"))
    </button>
    </div>
    [@react.component]
    let make = (~store: Store.storeBag) => {
    <div>
    <b> {("User: " ++ store.state.username)->React.string} </b>
    <br />
    <br />
    <span>
    {("Count: " ++ string_of_int(store.state.count))->React.string}
    </span>
    <br />
    <button onClick={_event => store.dispatch(Increase)}>
    "Increase"->React.string
    </button>
    <button onClick={_event => store.dispatch(Decrease)}>
    "Decrease"->React.string
    </button>
    </div>;
    };
    };

    @@ -65,46 +78,41 @@ module Router = {
    type action =
    | SwitchRoute(route);
    type routerState = {activeRoute: route};
    let component = ReasonReact.reducerComponent("Router");
    let make = _children => {
    ...component,
    initialState: () => {activeRoute: Login},
    reducer: (action, _state) =>
    switch action {
    | SwitchRoute(r) => ReasonReact.Update({activeRoute: r})
    let reducer = (state: routerState, action: action) =>
    switch (action) {
    | SwitchRoute(route) => {activeRoute: route}
    };

    [@react.component]
    let make = () => {
    let (state, dispatch) = React.useReducer(reducer, {activeRoute: Login});

    let url = ReasonReactRouter.useUrl();
    React.useEffect1(
    () => {
    switch (url.hash) {
    | "loggedin" => dispatch(SwitchRoute(Screen))
    | _ =>
    Js.log("Could not find route");
    Js.log(url);
    };
    None;
    },
    subscriptions: self => [
    Sub(
    () =>
    ReasonReact.Router.watchUrl(url => {
    switch url.path {
    | ["loggedin"] => self.send(SwitchRoute(Screen))
    | _ =>
    Js.log("Could not find route");
    Js.log(url);
    };
    ();
    }),
    ReasonReact.Router.unwatchUrl
    )
    ],
    render: self =>
    <Store
    render=(
    store =>
    <div>
    (
    switch self.state.activeRoute {
    | Screen => <Screen store />
    | Login => <Login />
    }
    )
    </div>
    )
    />
    [|url|],
    );

    <Store>
    ...{store =>
    <div>
    {switch (state.activeRoute) {
    | Screen => <Screen store />
    | Login => <Login store />
    }}
    </div>
    }
    </Store>;
    };
    };

    let component = ReasonReact.statelessComponent("Counter");

    let make = _children => {...component, render: _self => <Router />};
    [@react.component]
    let default = () => <Router />;
  2. jsiebern created this gist Feb 8, 2018.
    110 changes: 110 additions & 0 deletions StoreAndRouterExample.re
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,110 @@
    module Store = {
    type actions =
    | Increase
    | Decrease;
    type state = {count: int};
    type store = {
    state,
    dispatch: actions => unit
    };
    let component = ReasonReact.reducerComponent("Store");
    let make = (~render, _children) => {
    ...component,
    initialState: () => {count: 0},
    reducer: (action, state) =>
    switch action {
    | Increase => ReasonReact.Update({count: state.count + 1})
    | Decrease => ReasonReact.Update({count: state.count - 1})
    },
    render: self =>
    render({state: self.state, dispatch: action => self.send(action)})
    };
    };

    module Login = {
    let component = ReasonReact.statelessComponent("Login");
    let make = _children => {
    ...component,
    render: _self =>
    <div>
    <button onClick=(_event => ReasonReact.Router.push("/loggedin"))>
    (ReasonReact.stringToElement("Login"))
    </button>
    </div>
    };
    };

    module Screen = {
    let component = ReasonReact.statelessComponent("Screen");
    let make = (~store: Store.store, _children) => {
    ...component,
    render: _self =>
    <div>
    <span>
    (
    ReasonReact.stringToElement(
    "Count: " ++ string_of_int(store.state.count)
    )
    )
    </span>
    <br />
    <button onClick=(_event => store.dispatch(Increase))>
    (ReasonReact.stringToElement("Increase"))
    </button>
    <button onClick=(_event => store.dispatch(Decrease))>
    (ReasonReact.stringToElement("Decrease"))
    </button>
    </div>
    };
    };

    module Router = {
    type route =
    | Login
    | Screen;
    type action =
    | SwitchRoute(route);
    type routerState = {activeRoute: route};
    let component = ReasonReact.reducerComponent("Router");
    let make = _children => {
    ...component,
    initialState: () => {activeRoute: Login},
    reducer: (action, _state) =>
    switch action {
    | SwitchRoute(r) => ReasonReact.Update({activeRoute: r})
    },
    subscriptions: self => [
    Sub(
    () =>
    ReasonReact.Router.watchUrl(url => {
    switch url.path {
    | ["loggedin"] => self.send(SwitchRoute(Screen))
    | _ =>
    Js.log("Could not find route");
    Js.log(url);
    };
    ();
    }),
    ReasonReact.Router.unwatchUrl
    )
    ],
    render: self =>
    <Store
    render=(
    store =>
    <div>
    (
    switch self.state.activeRoute {
    | Screen => <Screen store />
    | Login => <Login />
    }
    )
    </div>
    )
    />
    };
    };

    let component = ReasonReact.statelessComponent("Counter");

    let make = _children => {...component, render: _self => <Router />};