Skip to content

Instantly share code, notes, and snippets.

@ccapndave
Created August 23, 2018 08:09
Show Gist options
  • Save ccapndave/50f2a9d9e1ccb6cc76e7f61ea9556b0a to your computer and use it in GitHub Desktop.
Save ccapndave/50f2a9d9e1ccb6cc76e7f61ea9556b0a to your computer and use it in GitHub Desktop.
module type SelectData = {
type t;
let id: t => string;
let toString: t => string;
};
module Styles = {
open Css;
let search = style([width(px(300)), fontSize(px(20))]);
};
module MakeSelect = (Data: SelectData) => {
type state = {
searchTerm: string,
results: Belt.List.t(Data.t),
};
type action =
| SetSearch(string)
| SetResults(list(Data.t));
let reactList = list => list->Belt.List.toArray->ReasonReact.array;
let component = ReasonReact.reducerComponent("Select");
let make = (~findResult: string => Js.Promise.t(list(Data.t)), _children) => {
...component,
initialState: () => {searchTerm: "", results: []},
reducer: (action: action, state: state) =>
switch (action) {
| SetSearch(searchTerm) =>
ReasonReact.UpdateWithSideEffects(
{...state, searchTerm},
(
self =>
findResult(searchTerm)
|> Js.Promise.then_(dataList =>
self.send(SetResults(dataList)) |> Js.Promise.resolve
)
|> ignore
),
)
| SetResults(results) => ReasonReact.Update({...state, results})
},
render: self => {
let renderedResults =
self.state.results
->Belt.List.map(result =>
<li key={Data.id(result)}>
{ReasonReact.string(result->Data.toString)}
</li>
);
<div>
<input
className=Styles.search
value={self.state.searchTerm}
onChange={
event =>
self.send(SetSearch(event->ReactEvent.Form.target##value))
}
/>
<ol> {reactList(renderedResults)} </ol>
</div>;
},
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment