UNPKG

reason-recoil

Version:

![Node.js CI](https://github.com/bloodyowl/reason-recoil/workflows/Node.js%20CI/badge.svg)

201 lines (149 loc) 3.98 kB
# reason-recoil ![Node.js CI](https://github.com/bloodyowl/reason-recoil/workflows/Node.js%20CI/badge.svg) > Zero-cost bindings to Facebook's [Recoil](https://recoiljs.org) library ⚠️ These bindings are still in experimental stages, use with caution ## Installation Run the following command: ```console $ yarn add recoil reason-recoil ``` Then add `reason-recoil` to your `bsconfig.json`'s dependencies: ```diff { "bs-dependencies": [ + "reason-recoil" ] } ``` ## Usage ### Atom ```reason let textState = Recoil.atom({ key: "textState", default: "", }); ``` ### Selector A nice feature the OCaml type-system enables is the ability to differenciate Recoil values between the ones that can **only read state** with the ones that can **write state**. This way, you **can't** use hooks with write capabilities with a read-only value. #### With read only capabilities ```reason let textStateSize = Recoil.selector({ key: "textStateSize", get: ({get}) => { let textState = get(textState); Js.String.length(textState); }, }); ``` #### With write capabilities ```reason let textStateSize = Recoil.selector({ key: "textStateSize", get: ({get}) => { let textState = get(textState); Js.String.length(textState); }, set: ({set}, newSize) => { let currentTextState = get(textState); set(textState, currentTextState->Js.String.slice(~from=0, ~to_=newSize)); } }); ``` #### Async ```reason let user = Recoil.asyncSelector({ key: "user", get: ({get}) => { fetchUser(get(currentUserId)) }, }); ``` ### Hooks #### `useRecoilState` ```reason let (state, setState) = Recoil.useRecoilState(textState); state; // read setState(textState => newTextState); // write ``` #### `useRecoilValue` ```reason let state = Recoil.useRecoilValue(textState); state; // read ``` #### `useSetRecoilState` ```reason let setState = Recoil.useSetRecoilState(textState); setState(textState => newTextState); // write ``` #### `useResetRecoilState` ```reason let reset = Recoil.useResetRecoilState(textState); reset(); // write ``` #### `useRecoilCallback` - Dependency free (reevaluates the callback at every render): `useRecoilCallback(...)` - Zero-dependency (never reevaluates the callback): `useRecoilCallback0(...)` - One-dependency (reevaluates when dep changes): `useRecoilCallback1(..., [|dep|])` - Multiple-dependencies: `useRecoilCallback2(..., (dep1, dep2))` (goes from 2 to 5) ```reason let onClick = Recoil.useRecoilCallback(({snapshot: {getPromise}}, event) => { let _ = getPromise(myAtom) |> Js.Promise.then_(value => { Js.log(value); Js.Promise.resolve() }); }); <button onClick={onClick}> "Click me"->React.string </button> ``` #### `useRecoilValueLoadable` ```reason let loadable = Recoil.useRecoilValueLoadable(textState); Js.log(loadable->Recoil.Loadable.state); Js.log(loadable->Recoil.Loadable.getValue); ``` ## Examples The [Recoil Basic Tutorial](https://recoiljs.org/docs/basic-tutorial/intro) has been made in ReasonReact: [check the source](./examples/TodoList.re)! You can run it using: ```console $ yarn examples ``` and going to [http://localhost:8000/TodoList.html](http://localhost:8000/TodoList.html) ### Memoization ```reason type t = { id: string, value: string, isCompleted: bool, }; // For atoms let todoItemFamily = Recoil.atomFamily({ key: "todo", default: param => { id: param, value: "", isCompleted: false, }, }); // For selectors let todoItemLengthFamily = Recoil.selectorFamily({ key: "todo", // The `Fn` wrapper is needed here so that BuckleScript // outputs the correct value get: param => Fn(({get}) => { get(todoItemFamily(param)).value->Js.String2.length; }), }); ``` And use it within a React component: ```reason [@react.component] let make = (~todoId) => { let (todo, setTodo) = Recoil.useRecoilState(todoItemFamily(id)); // ... <> {todo.value->React.string} </> }; ```