diff --git a/data/sidebar_react_v0110.json b/data/sidebar_react_v0110.json
new file mode 100644
index 000000000..f7e96a22c
--- /dev/null
+++ b/data/sidebar_react_v0110.json
@@ -0,0 +1,31 @@
+{
+ "Overview": [
+ "introduction",
+ "installation",
+ "migrate-react"
+ ],
+ "Main Concepts": [
+ "elements-and-jsx",
+ "rendering-elements",
+ "components-and-props",
+ "arrays-and-keys",
+ "refs-and-the-dom",
+ "context",
+ "styling",
+ "router"
+ ],
+ "Hooks & State Management": [
+ "hooks-overview",
+ "hooks-effect",
+ "hooks-state",
+ "hooks-reducer",
+ "hooks-context",
+ "hooks-ref",
+ "hooks-custom"
+ ],
+ "Guides": [
+ "beyond-jsx",
+ "forwarding-refs",
+ "extensions-of-props"
+ ]
+}
\ No newline at end of file
diff --git a/pages/docs/react/v0.11.0/arrays-and-keys.mdx b/pages/docs/react/v0.11.0/arrays-and-keys.mdx
new file mode 100644
index 000000000..56be3f290
--- /dev/null
+++ b/pages/docs/react/v0.11.0/arrays-and-keys.mdx
@@ -0,0 +1,127 @@
+---
+title: Arrays and Keys
+description: "Rendering arrays and handling keys in ReScript and React"
+canonical: "/docs/react/latest/arrays-and-keys"
+---
+
+# Arrays and Keys
+
+
+
+Whenever we are transforming data into an array of elements and put it in our React tree, we need to make sure to give every element an unique identifier to help React distinguish elements for each render. This page will explain the `key` attribute and how to apply it whenever we need to map data to `React.element`s.
+
+
+
+## Keys & Rendering Arrays
+
+Keys help React identify which elements have been changed, added, or removed throughout each render. Keys should be given to elements inside the array to give the elements a stable identity:
+
+```res
+let numbers = [1, 2, 3, 4, 5];
+
+let items = Belt.Array.map(numbers, (number) => {
+
{React.int(number)}
+})
+```
+
+The best way to pick a key is to use a string that uniquely identifies a list item among its siblings. Most often you would use IDs from your data as keys:
+
+```res
+type todo = {id: string, text: string}
+
+let todos = [
+ {id: "todo1", text: "Todo 1"},
+ {id: "todo2", text: "Todo 2"}
+]
+
+let items = Belt.Array.map(todos, todo => {
+
{React.string(todo.text)}
+})
+```
+
+If you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort:
+
+```res {1..3}
+let items = Belt.Array.mapWithIndex(todos, (i, todo) => {
+ // Only do this if items have no stable id
+
+ {todo.text}
+
+});
+```
+
+### Keys Must Only Be Unique Among Siblings
+
+Keys used within arrays should be unique among their siblings. However they don’t need to be globally unique. We can use the same keys when we produce two different arrays:
+
+```res {6,10,17,18,25,27}
+type post = {id: string, title: string, content: string}
+
+module Blog = {
+ @react.component
+ let make = (~posts: array) => {
+ let sidebar =
+
+ {
+ Belt.Array.map(posts, (post) => {
+
+ {React.string(post.title)}
+
+ })->React.array
+ }
+
+
+ let content = Belt.Array.map(posts, (post) => {
+
+
{React.string(post.title)}
+
{React.string(post.content)}
+
+ });
+
+
+ {sidebar}
+
+ {React.array(content)}
+
+ }
+}
+
+let posts = [
+ {id: "1", title: "Hello World", content: "Welcome to learning ReScript & React!"},
+ {id: "2", title: "Installation", content: "You can install reason-react from npm."}
+]
+
+let blog =
+```
+
+
+## Rendering `list` Values
+
+In case you ever want to render a `list` of items, you can do something like this:
+
+```res
+type todo = {id: string, text: string}
+
+@react.component
+let make = () => {
+ let todoList = list{
+ {id: "todo1", text: "Todo 1"},
+ {id: "todo2", text: "Todo 2"},
+ }
+
+ let items =
+ todoList
+ ->Belt.List.toArray
+ ->Belt.Array.map(todo => {
+
{React.string(todo.text)}
+ })
+
+
{React.array(items)}
+}
+
+```
+
+We use `Belt.List.toArray` to convert our list to an array before creating our `array`. Please note that using `list` has performance impact due to extra conversion costs.
+
+99% of the time you'll want to use arrays (seamless interop, faster JS code), but in some cases it might make sense to use a `list` to leverage advanced pattern matching features etc.
+
diff --git a/pages/docs/react/v0.11.0/beyond-jsx.mdx b/pages/docs/react/v0.11.0/beyond-jsx.mdx
new file mode 100644
index 000000000..bb4a12411
--- /dev/null
+++ b/pages/docs/react/v0.11.0/beyond-jsx.mdx
@@ -0,0 +1,220 @@
+---
+title: Beyond JSX
+description: "Details on how to use ReScript and React without JSX"
+canonical: "/docs/react/latest/beyond-jsx"
+---
+
+# Beyond JSX
+
+
+
+JSX is a syntax sugar that allows us to use React components in an HTML like manner. A component needs to adhere to certain interface conventions, otherwise it can't be used in JSX. This section will go into detail on how the JSX transformation works and what React APIs are used underneath.
+
+
+
+**Note:** This section requires knowledge about the low level apis for [creating elements](./elements-and-jsx#creating-elements-from-component-functions), such as `React.createElement` or `ReactDOM.createDOMElementVariadic`.
+
+> **Note:** This page assumes your `bsconfig.json` to be set to `"jsx": { "version": 4 }` to apply the right JSX transformations.
+
+## Component Types
+
+A plain React component is defined as a `('props) => React.element` function. You can also express a component more efficiently with our shorthand type `React.component<'props>`.
+
+Here are some examples on how to define your own component types (often useful when interoping with existing JS code, or passing around components):
+
+```res
+// Plain function type
+type friend = {name: string, online: bool}
+type friendComp = friend => React.element
+
+// Equivalent to
+// ({padding: string, children: React.element}) => React.element
+type props = {padding: string, children: React.element}
+type containerComp = React.component
+```
+The types above are pretty low level (basically the JS representation of a React component), but since ReScript React has its own ways of defining React components in a more language specific way, let's have a closer look on the anatomy of such a construct.
+
+## JSX Component Interface
+
+A ReScript React component needs to be a (sub-)module with a `make` function and `props` type to be usable in JSX. To make things easier, we provide a `@react.component` decorator to create those functions for you:
+
+
+
+```res
+module Friend = {
+ @react.component
+ let make = (~name: string, ~children) => {
+
+ {React.string(name)}
+ children
+
+ }
+}
+```
+```res
+module Friend = {
+ type props<'name, 'children> = {
+ name: 'name,
+ children: 'children,
+ }
+
+ let make = ({name, children, _}: props) => {
+ ReactDOM.createDOMElementVariadic("div", [{React.string(name)}, children])
+ }
+}
+```
+
+
+
+In the expanded output:
+
+- `props`: A generated record type that has fields according to the labeled arguments of the `make` function
+- `make`: A converted `make` function that complies to the component interface `(props) => React.element`
+
+### Special Case React.forwardRef
+
+The `@react.component` decorator also works for `React.forwardRef` calls:
+
+
+
+
+```res
+module FancyInput = {
+ @react.component
+ let make = React.forwardRef((~className=?, ~children, ref) =>
+
+ // use ref here
+
+ )
+}
+```
+
+```res
+// Simplified Output
+type props<'className, 'children, 'ref> = {
+ className?: 'className,
+ children: 'children,
+ ref?: 'ref,
+}
+
+let make = (
+ {?className, children, _}: props<'className, 'children, ReactRef.currentDomRef>,
+ ref: Js.Nullable.t,
+) =>
+ make(~className, ~children, ~ref, ())
+```
+
+
+
+As shown in the expanded output above, our decorator desugars the function passed to `React.forwardRef` in the same manner as a typical component `make` function. It also creates a `props` type with an optional `ref` field, so we can use it in our JSX call (``).
+
+So now that we know how the ReScript React component transformation works, let's have a look on how ReScript transforms our JSX constructs.
+
+## JSX Under the Hood
+
+Whenever we are using JSX with a custom component ("capitalized JSX"), we are actually using `React.createElement` to create a new element. Here is an example of a React component without children:
+
+
+
+```res
+
+```
+```res
+// classic
+React.createElement(Friend.make, {name: "Fred", age:20})
+
+// automatic
+React.jsx(Friend.make, {name: "Fred", age: 20})
+```
+```js
+React.createElement(Playground$Friend, { name: "Fred", age: 20 });
+```
+
+
+
+As you can see, it uses `Friend.make` to call the `React.createElement` API. In case you are providing children, it will use `React.createElementVariadic` instead (which is just a different binding for `React.createElement`):
+
+
+
+```res
+
+ {React.string("Hello")}
+ {React.string("World")}
+
+```
+
+```res
+// classic
+React.createElementVariadic(
+ Container.make,
+ {width: 200, children: React.null},
+ [{React.string("Hello")}, {React.string("World")}],
+)
+
+// automatic
+React.jsxs(
+ Container.make,
+ {width: 200, children: React.array([{React.string("Hello")}, {React.string("World")}])},
+)
+```
+
+```js
+React.createElement(Container, { width: 200, children: null }, "Hello", "World");
+```
+
+
+
+Note that the `children: React.null` field has no relevance since React will only care about the children array passed as a third argument.
+
+
+### Dom Elements
+
+"Uncapitalized JSX" expressions are treated as DOM elements and will be converted to `ReactDOM.createDOMElementVariadic` calls:
+
+
+
+```res
+
+```
+
+```res
+// classic
+ReactDOM.createDOMElementVariadic("div", ~props={title: "test"}, [])
+
+// automatic
+ReactDOM.jsx("div", {title: "test"})
+```
+
+```js
+React.createElement("div", { title: "test" });
+```
+
+
+
+The same goes for uncapitalized JSX with children:
+
+
+
+```res
+
+
+
+```
+
+```res
+// classic
+ReactDOM.createDOMElementVariadic(
+ "div",
+ ~props={title: "test"},
+ [ReactDOM.createDOMElementVariadic("span", [])],
+)
+
+// automatic
+ReactDOM.jsx("div", {title: "test", children: ?ReactDOM.someElement(ReactDOM.jsx("span", {}))})
+```
+
+```js
+React.createElement("div", { title: "test" }, React.createElement("span", undefined));
+```
+
+
diff --git a/pages/docs/react/v0.11.0/components-and-props.mdx b/pages/docs/react/v0.11.0/components-and-props.mdx
new file mode 100644
index 000000000..7d21b1d68
--- /dev/null
+++ b/pages/docs/react/v0.11.0/components-and-props.mdx
@@ -0,0 +1,424 @@
+---
+title: Components and Props
+description: "Basic concepts for components and props in ReScript & React"
+canonical: "/docs/react/latest/components-and-props"
+---
+
+# Components and Props
+
+
+
+Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. This page provides an introduction to the idea of components.
+
+
+
+## What is a Component?
+
+A React component is a function describing a UI element that receives a `props` object as a parameter (data describing the dynamic parts of the UI) and returns a `React.element`.
+
+The nice thing about this concept is that you can solely focus on the input and output. The component function receives some data and returns some opaque `React.element` that is managed by the React framework to render your UI.
+
+> If you want to know more about the low level details on how a component interface is implemented, refer to the [Beyond JSX](./beyond-jsx) page.
+
+## Component Example
+
+Let's start with a first example to see how a ReScript React component looks like:
+
+
+
+```res
+// src/Greeting.res
+@react.component
+let make = () => {
+
+ {React.string("Hello ReScripters!")}
+
+}
+```
+```js
+import * as React from "react";
+
+function Greeting(props) {
+ return React.createElement("div", undefined, "Hello ReScripters!");
+}
+
+var make = Greeting;
+```
+
+
+
+**Important:** Always make sure to name your component function `make`.
+
+We've created a `Greeting.res` file that contains a `make` function that doesn't receive any props (the function doesn't receive any parameters), and returns a `React.element` that represents `
Hello ReScripters!
` in the rendered DOM.
+
+You can also see in the the JS output that the function we created was directly translated into the pure JS version of a ReactJS component. Note how a `
` transforms into a `React.createElement("div",...)` call in JavaScript.
+
+## Defining Props
+
+In ReactJS, props are usually described as a single `props` record. In ReScript, we use [labeled arguments](/docs/manual/latest/function#labeled-arguments) to define our props parameters instead. Here's an example:
+
+
+
+```res
+// src/Article.res
+@react.component
+let make = (~title: string, ~visitorCount: int, ~children: React.element) => {
+ let visitorCountMsg = "You are visitor number: " ++ Belt.Int.toString(visitorCount);
+
+
{React.string(title)}
+
{React.string(visitorCountMsg)}
+ children
+
+}
+```
+```js
+import * as React from "react";
+
+function Article(props) {
+ var visitorCountMsg = "You are visitor number: " + String(props.visitorCount);
+ return React.createElement("div", undefined, React.createElement("div", undefined, props.title), React.createElement("div", undefined, visitorCountMsg), props.children);
+}
+
+var make = Article;
+```
+
+
+
+### Optional Props
+
+We can leverage the full power of labeled arguments to define optional props as well:
+
+
+
+```res
+// Greeting.res
+@react.component
+let make = (~name: option=?) => {
+ let greeting = switch name {
+ | Some(name) => "Hello " ++ name ++ "!"
+ | None => "Hello stranger!"
+ }
+
{React.string(greeting)}
+}
+```
+
+```js
+function Greeting(props) {
+ var name = props.name;
+ var greeting = name !== undefined ? "Hello " + name + "!" : "Hello stranger!";
+ return React.createElement("div", undefined, greeting);
+}
+```
+
+
+
+**Note:** The `@react.component` attribute implicitly adds the last `()` parameter to our `make` function for us (no need to do it ourselves).
+
+In JSX, you can apply optional props with some special syntax:
+
+
+
+```res
+let name = Some("Andrea")
+
+
+```
+
+```js
+var name = "Andrea";
+
+React.createElement(Greeting, {
+ name: name
+});
+```
+
+
+
+### Special Props `key` and `ref`
+
+You can't define any props called `key` or `ref`. React treats those props differently and the compiler will yield an error whenever you try to define a `~key` or `~ref` argument in your component function.
+
+Check out the corresponding [Arrays and Keys](./arrays-and-keys) and [Forwarding React Refs](./forwarding-refs) sections for more details.
+
+### Handling Invalid Prop Names (e.g. keywords)
+
+Prop names like `type` (as in ``) aren't syntactically valid; `type` is a reserved keyword in ReScript. Use `` instead.
+
+For `aria-*` use camelCasing, e.g., `ariaLabel`. For DOM components, we'll translate it to `aria-label` under the hood.
+
+For `data-*` this is a bit trickier; words with `-` in them aren't valid in ReScript. When you do want to write them, e.g., ``, check out the [React.cloneElement](./elements-and-jsx#cloning-elements) or [React.createDOMElementVariadic](./elements-and-jsx#creating-dom-elements) section.
+
+
+## Children Props
+
+In React `props.children` is a special attribute to represent the nested elements within a parent element:
+
+```res
+let element =
child1 child2
+```
+
+By default, whenever you are passing children like in the expression above, `children` will be treated
+as a `React.element`:
+
+
+
+```res
+module MyList = {
+ @react.component
+ let make = (~children: React.element) => {
+
+ children
+
+ }
+}
+
+
+
{React.string("Item 1")}
+
{React.string("Item 2")}
+
+```
+
+```js
+function MyList(props) {
+ return React.createElement("ul", undefined, props.children);
+}
+
+var MyList = {
+ make: MyList
+};
+
+React.createElement(MyList, {
+ children: null
+ }, React.createElement("li", undefined, "Item 1"),
+ React.createElement("li", undefined, "Item 2"));
+```
+
+
+
+Interestingly, it doesn't matter if you are passing just one element, or several, React will always collapse its children to a single `React.element`.
+
+It is also possible to redefine the `children` type as well. Here are some examples:
+
+**Component with a mandatory `string` as children:**
+
+```res
+module StringChildren = {
+ @react.component
+ let make = (~children: string) => {
+
+ {React.string(children)}
+
+ }
+}
+
+ "My Child"
+
+// This will cause a type check error
+
+```
+
+**Component with an optional `React.element` as children:**
+
+```res
+module OptionalChildren = {
+ @react.component
+ let make = (~children: option=?) => {
+
+ {switch children {
+ | Some(element) => element
+ | None => React.string("No children provided")
+ }}
+
+ }
+}
+
+
+
+
+
+```
+
+**Component that doesn't allow children at all:**
+
+```res
+module NoChildren = {
+ @react.component
+ let make = () => {
+
+ {React.string("I don't accept any children params")}
+
+ }
+}
+
+// The compiler will raise a type error here
+
+```
+
+Children props are really tempting to be abused as a way to model hierarchies, e.g. `` (`List` should only allow `Item` / `ListHeader` elements), but this kind of constraint is hard to enforce because all components end up being a `React.element`, so it would require notorious runtime checking within `List` to verify that all children are in fact of type `Item` or `ListHeader`.
+
+The best way to approach this kind of issue is by using props instead of children, e.g. ``. This way it's easy to type check the constraints, and it also spares component consumers from memorizing and remembering component constraints.
+
+**The best use-case for `children` is to pass down `React.element`s without any semantic order or implementation details!**
+
+
+## Props & Type Inference
+
+The ReScript type system is really good at inferring the prop types just by looking at its prop usage.
+
+For simple cases, well-scoped usage, or experimentation, it's still fine to omit type annotations:
+
+
+```res
+// Button.res
+
+@react.component
+let make = (~onClick, ~msg, ~children) => {
+
+ {React.string(msg)}
+ children
+
+}
+```
+
+In the example above, `onClick` will be inferred as `ReactEvent.Mouse.t => unit`, `msg` as `string` and `children` as `React.element`. Type inference is especially useful when you just forward values to some smaller (privately scoped) functions.
+
+Even though type inference spares us a lot of keyboard typing, we still recommend to explicitly type your props (just like with any public API) for better type visibility and to prevent confusing type errors.
+
+## Using Components in JSX
+
+Every ReScript component can be used in JSX. For example, if we want to use our `Greeting` component within our `App` component, we can do this:
+
+
+
+```res
+// src/App.res
+
+@react.component
+let make = () => {
+
+
+
+}
+```
+```js
+var React = require("react");
+var Greeting = require("./Greeting.js")
+
+function App(Props) {
+ return React.createElement("div", undefined, React.createElement(Greeting.make, {}));
+}
+
+var make = App;
+```
+
+
+
+**Note:** React components are capitalized; primitive DOM elements like `div` or `button` are uncapitalized. More infos on the JSX specifics and code transformations can be found in our [JSX language manual section](/docs/manual/latest/jsx#capitalized-tag).
+
+
+### Handwritten Components
+
+You don't need to use the `@react.component` decorator to write components that can be used in JSX. Instead you can write the `make` function with type `props` and these will always work as React components. But then you will have the issue with the component name being "make" in the React dev tools.
+
+For example:
+
+
+
+```res
+module Link = {
+ type props = {href: string, children: React.element};
+
+ let make = (props: props) => {
+
+ {props.children}
+
+ }
+}
+
+ {React.string("Docs")}
+```
+```js
+function make(props) {
+ return React.createElement(
+ "a",
+ { href: props.href },
+ props.children
+ );
+}
+
+var Link = {
+ make: make,
+};
+
+React.createElement(make, {
+ href: "/docs",
+ children: "Docs",
+});
+```
+
+
+
+More details on the `@react.component` decorator and its generated interface can be found in our [Beyond JSX](./beyond-jsx) page.
+
+
+## Submodule Components
+
+We can also represent React components as submodules, which makes it very convenient to build more complex UI without the need to create multiple files for each composite component (that's probably only used by the parent component anyways):
+
+```res
+// src/Button.res
+module Label = {
+ @react.component
+ let make = (~title: string) => {
+
+}
+```
+
+The `Button.res` file defined above is now containing a `Label` component, that can also be used by other components, either by writing the fully qualified module name (``) or by using a module alias to shortcut the full qualifier:
+
+
+```res
+module Label = Button.Label
+
+let content =
+```
+
+## Component Naming
+
+Because components are actually a pair of functions, they have to belong to a module to be used in JSX. It makes sense to use these modules for identification purposes as well. `@react.component` automatically adds the name for you based on the module you are in.
+
+
+```res
+// File.res
+
+// will be named `File` in dev tools
+@react.component
+let make = ...
+
+// will be named `File$component` in dev tools
+@react.component
+let component = ...
+
+module Nested = {
+ // will be named `File$Nested` in dev tools
+ @react.component
+ let make = ...
+};
+```
+
+If you need a dynamic name for higher-order components or you would like to set your own name you can use `React.setDisplayName(make, "NameThatShouldBeInDevTools")`.
+
+
+## Tips & Tricks
+
+- Start with one component file and utilize submodule components as your component grows. Consider splitting up in multiple files when really necessary.
+- Keep your directory hierarchy flat. Instead of `article/Header.res` use `ArticleHeader.res` etc. Filenames are unique across the codebase, so filenames tend to be very specific `ArticleUserHeaderCard.res`, which is not necessarily a bad thing, since it clearly expresses the intent of the component within its name, and makes it also very easy to find, match and refactor across the whole codebase.
diff --git a/pages/docs/react/v0.11.0/context.mdx b/pages/docs/react/v0.11.0/context.mdx
new file mode 100644
index 000000000..66eef63a4
--- /dev/null
+++ b/pages/docs/react/v0.11.0/context.mdx
@@ -0,0 +1,202 @@
+---
+title: Context
+description: "Details about Context in ReScript and React"
+canonical: "/docs/react/latest/context"
+---
+
+# Context
+
+
+
+Context provides a way to pass data through the component tree without having to pass props down manually at every level.
+
+
+
+## Why Context?
+
+In a typical React application, data is passed top-down (parent to child) via props, but this can be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required by many components within an application. Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree.
+
+**Note:** In ReScript, passing down props is way simpler than in TS / JS due to its [JSX prop punning](/docs/manual/latest/jsx#punning) feature and strong type inference, so it's often preferrable to keep it simple and just do props passing. Less magic means more transparency!
+
+
+## When to Use Context
+
+Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language. For example, in the code below we manually thread through a “theme” prop in order to style the Button component:
+
+
+
+```res
+// src/App.res
+type theme = Light | Dark;
+
+module Button = {
+ @react.component
+ let make = (~theme) => {
+ let className = switch theme {
+ | Light => "theme-light"
+ | Dark => "theme-black"
+ };
+
+ }
+}
+
+module ThemedButton = {
+ @react.component
+ let make = (~theme) => {
+
+ }
+}
+
+module Toolbar = {
+ @react.component
+ let make = (~theme) => {
+
+
+
+ }
+}
+
+@react.component
+let make = () => {
+ // We define the theme in the
+ // toplevel App component and
+ // pass it down
+
+}
+```
+
+```js
+function Button(props) {
+ var className = props.theme ? "theme-black" : "theme-light";
+ return React.createElement("button", {
+ className: className
+ }, "Click me");
+}
+
+function ThemedButton(props) {
+ return React.createElement(App$Button, {
+ theme: props.theme
+ });
+}
+
+function Toolbar(props) {
+ return React.createElement("div", undefined, React.createElement(App$ThemedButton, {
+ theme: props.theme
+ }));
+}
+
+function App(props) {
+ return React.createElement(App$Toolbar, {
+ theme: /* Dark */1
+ });
+}
+```
+
+
+Using context, we can avoid passing props through intermediate elements:
+
+
+
+```res
+// src/App.res
+
+module ThemeContext = {
+ type theme = Light | Dark
+ let context = React.createContext(Light)
+
+ module Provider = {
+ let make = React.Context.provider(context)
+ }
+}
+
+module Button = {
+ @react.component
+ let make = (~theme) => {
+ let className = switch theme {
+ | ThemeContext.Light => "theme-light"
+ | Dark => "theme-black"
+ }
+
+ }
+}
+
+module ThemedButton = {
+ @react.component
+ let make = () => {
+ let theme = React.useContext(ThemeContext.context)
+
+
+ }
+}
+
+module Toolbar = {
+ @react.component
+ let make = () => {
+
+
+}
+```
+```js
+var context = React.createContext(/* Light */0);
+
+var make = context.Provider;
+
+var Provider = {
+ make: make
+};
+
+var ThemeContext = {
+ context: context,
+ Provider: Provider
+};
+
+function App$Button(props) {
+ var className = props.theme ? "theme-black" : "theme-light";
+ return React.createElement("button", {
+ className: className
+ }, "Click me");
+}
+
+var Button = {
+ make: App$Button
+};
+
+function App$ThemedButton(props) {
+ var theme = React.useContext(context);
+ return React.createElement(App$Button, {
+ theme: theme
+ });
+}
+
+var ThemedButton = {
+ make: App$ThemedButton
+};
+
+function App$Toolbar(props) {
+ return React.createElement("div", undefined, React.createElement(App$ThemedButton, {}));
+}
+
+var Toolbar = {
+ make: App$Toolbar
+};
+
+function App(props) {
+ return React.createElement(make, {
+ value: /* Dark */1,
+ children: React.createElement("div", undefined, React.createElement(App$Toolbar, {}))
+ });
+}
+```
+
+
diff --git a/pages/docs/react/v0.11.0/elements-and-jsx.mdx b/pages/docs/react/v0.11.0/elements-and-jsx.mdx
new file mode 100644
index 000000000..571f7b966
--- /dev/null
+++ b/pages/docs/react/v0.11.0/elements-and-jsx.mdx
@@ -0,0 +1,221 @@
+---
+title: Elements & JSX
+description: "Basic concepts for React elements and how to use them in JSX"
+canonical: "/docs/react/latest/elements-and-jsx"
+---
+
+# Elements & JSX
+
+
+
+Elements are the smallest building blocks of React apps. This page will explain how to handle `React.element`s in your React app with our dedicated JSX syntax.
+
+
+
+> **Note:** This page assumes your `bsconfig.json` to be set to `"jsx": { "version": 4 }`, otherwise your JSX will not be transformed to its React specific form.
+
+## Element Basics
+
+Let's start out by creating our first React element.
+
+```res
+let element =
{React.string("Hello World")}
+```
+
+The binding `element` and the expression `{React.string("Hello World")}` are both of type `React.element`, the fundamental type for representing React elements within a React application. An element describes what you see on the screen whenever you render your application to the DOM.
+
+Let's say you want to create a function that handles another React element, such as `children`, you can annotate it as `React.element`:
+
+```res
+let wrapChildren = (children: React.element) => {
+
+
{React.string("Overview")}
+ children
+
+}
+
+wrapChildren(
{React.string("Let's use React with ReScript")}
)
+```
+
+Understanding the definition of a `React.element` is essential since it is heavily used within the React APIs, such as `ReactDOM.Client.Root.render(..., element)`, etc. Be aware that JSX doesn't do any automatic `string` to `React.element` conversion for you (ReScript forces explicit type conversion). For example `
Hello World
` will not type-check (which is actually a good thing because it's also a huge source for subtle bugs!), you need to convert your `"Hello World"` with the `React.string` function first.
+
+Fortunately our React bindings bring all necessary functionality to represent all relevant data types as `React.element`s.
+
+## Using Elements within JSX
+
+You can compose elements into more complex structures by using JSX:
+
+```res
+let greeting = React.string("Hello ")
+let name = React.string("Stranger");
+
+
+// element is also of type React.element
+let element =
greeting name
+```
+
+JSX is the main way to express your React application as a tree of elements.
+
+Sometimes, when doing a lot of interop with existing ReactJS codebases, you'll find yourself in a situation where you can't use JSX syntax due to syntactic restrictions. Check out the [Escape Hatches](#escape-hatches) chapter later on for workarounds.
+
+## Creating Elements
+
+### Creating Elements from `string`, `int`, `float`, `array`
+
+Apart from using JSX to create our React elements or React components, the `React` module offers various functions to create elements from primitive data types:
+
+```res
+React.string("Hello") // new element representing "Hello"
+
+React.int(1) // new element representing "1"
+
+React.float(1.0) // new element representing "1.0"
+```
+
+It also offers `React.array` to represent multiple elements as one single element (useful for rendering a list of data, or passing children):
+
+```res
+let element = React.array([
+ React.string("element 1"),
+ React.string("element 2"),
+ React.string("element 3")
+])
+```
+
+**Note:** We don't offer a `React.list` function because a `list` value would impose runtime overhead. ReScript cares about clean, idiomatic JS output. If you want to transform a `list` of elements to a single React element, combine the output of `Belt.List.toArray` with `React.array` instead.
+
+### Creating Null Elements
+
+ReScript doesn't allow `element || null` constraints due to it's strongly typed nature. Whenever you are expressing conditionals where a value might, or might not be rendered, you will need the `React.null` constant to represent *Nothingness*:
+
+
+
+
+```res
+let name = Some("Andrea")
+
+let element = switch name {
+ | Some(name) =>
{React.string("Hello " ++ name)}
+ | None => React.null
+}
+
+
element
+```
+```js
+var name = "Andrea";
+
+var element = name !== undefined ? React.createElement("div", undefined, "Hello " + name) : null;
+
+React.createElement("div", undefined, element);
+```
+
+
+
+## Escape Hatches
+
+**Note:** This chapter features low level APIs that are used by JSX itself, and should only be used whenever you hit certain JSX syntax limitations. More infos on the JSX internals can be found in our [Beyond JSX](./beyond-jsx) section.
+
+### Creating Elements from Component Functions
+
+**Note:** Details on components and props will be described in the [next chapter](./components-and-props).
+
+Sometimes it's necessary to pass around component functions to have more control over `React.element` creation. Use the `React.createElement` function to instantiate your elements:
+
+```res
+type props = {name: string}
+
+let render = (myComp: props => React.element) => {
+
{React.createElement(myComp, {name: "Franz"})}
+}
+```
+
+This feature is often used when interacting with existing JS / ReactJS code. In pure ReScript React applications, you would rather pass a function that does the rendering for you (also called a "render prop"):
+
+```res
+let render = (renderMyComp: (~name: string) => React.element) => {
+
{renderMyComp(~name="Franz")}
+}
+```
+
+#### Pass Variadic Children
+
+There is also a `React.createElementVariadic` function, which takes an array of children as a third parameter:
+
+
+
+```res
+type props = {title: string, children: React.element}
+
+let render = (article: props => React.element) => {
+ let children = [React.string("Introduction"), React.string("Body")]
+
+ let props = {title: "Article #1", children: React.null}
+
+ {React.createElementVariadic(article, props, children)}
+}
+```
+```js
+function render(article) {
+ var children = [
+ "Introduction",
+ "Body"
+ ];
+ var props = {
+ title: "Article #1",
+ children: null
+ };
+ return Caml_splice_call.spliceApply(React.createElement, [
+ article,
+ props,
+ children
+ ]);
+}
+```
+
+
+
+**Note:** Here we are passing a prop `"children": React.null` to satisfy the type checker. React will ignore the children prop in favor of the children array.
+
+This function is mostly used by our JSX transformations, so usually you want to use `React.createElement` and pass a children prop instead.
+
+### Creating DOM Elements
+
+
+To create DOM elements (`
`, ``, etc.), use `ReactDOM.createDOMElementVariadic`:
+
+```res
+ReactDOM.createDOMElementVariadic("div", ~props={className: "card"}, [])
+```
+
+ReScript can make sure that we are only passing valid dom props. You can find an exhaustive list of all available props in the [JsxDOM](https://github.com/rescript-lang/rescript-compiler/blob/3bc159f33a3534280bbc26be88fa37ea2114dafe/jscomp/others/jsxDOM.res#L31) module.
+
+### Cloning Elements
+
+**Note:** This is an escape hatch feature and will only be useful for interoping with existing JS code / libraries.
+
+Sometimes it's required to clone an existing element to set, overwrite or add prop values to a new instance, or if you want to set invalid prop names such as `data-name`. You can use `React.cloneElement` for that:
+
+
+
+```res
+let original =
+
+// Will return a new React.element with className set to "world"
+React.cloneElement(original, {"className": "world", "data-name": "some name"});
+```
+```js
+var original = React.createElement("div", {
+ className: "hello"
+ });
+
+React.cloneElement(original, {
+ className: "world",
+ "data-name": "some name"
+ });
+```
+
+
+
+The feature mentioned above could also replicate `props spreading`, a practise commonly used in ReactJS codebases, but we strongly discourage the usage due to its unsafe nature and its incorrectness (e.g. adding undefined extra props to a component doesn't make sense, and causes hard to find bugs).
+
+In ReScript, we rather pass down required props explicitly to leaf components or use a renderProp instead. We introduced [JSX punning](/docs/manual/latest/jsx#punning) syntax to make the process of passing down props more convenient.
diff --git a/pages/docs/react/v0.11.0/extensions-of-props.mdx b/pages/docs/react/v0.11.0/extensions-of-props.mdx
new file mode 100644
index 000000000..b9b71ffaf
--- /dev/null
+++ b/pages/docs/react/v0.11.0/extensions-of-props.mdx
@@ -0,0 +1,141 @@
+---
+title: Extensions of props
+description: "Extensions of props in ReScript and React"
+canonical: "/docs/react/latest/spread-props"
+---
+
+# Extensions of Props
+
+> **Note:** This page assumes your `bsconfig.json` to be set to `"jsx": { "version": 4 }` to apply the right JSX transformations.
+
+## Spread props
+
+JSX props spread is supported now, but in a stricter way than in JS.
+
+
+
+```res
+
+```
+```js
+React.createElement(Comp, {
+ a: "a",
+ b: "b"
+});
+```
+
+
+
+Multiple spreads are not allowed:
+
+
+
+```res
+
+```
+
+
+
+The spread must be at the first position, followed by other props:
+
+
+
+```res
+
+```
+
+
+
+## Shared props
+
+You can control the definition of the `props` type by passing as argument to `@react.component` the body of the type definition of `props`. The main application is sharing a single type definition across several components. Here are a few examples:
+
+
+
+```res
+type sharedprops<'x, 'y> = {x: 'x, y: 'y, z:string}
+
+module C1 = {
+ @react.component(:sharedProps<'a, 'b>)
+ let make = (~x, ~y) => React.string(x ++ y ++ z)
+}
+
+module C2 = {
+ @react.component(:sharedProps)
+ let make = (~x, ~y) => React.string(x ++ y ++ z)
+}
+
+module C3 = {
+ type myProps = sharedProps
+ @react.component(:myProps)
+ let make = (~x, ~y) => React.int(x + y)
+}
+```
+
+```res
+type sharedprops<'x, 'y> = {x: 'x, y: 'y, z: string}
+
+module C1 = {
+ type props<'a, 'b> = sharedProps<'a, 'b>
+ let make = ({x, y, _}: props<_>) => React.string(x ++ y ++ z)
+}
+
+module C2 = {
+ type props<'b> = sharedProps
+ let make = ({x, y, _}: props<_>) => React.string(x ++ y ++ z)
+}
+
+module C3 = {
+ type myProps = sharedProps
+ type props = myProps
+ let make = ({x, y, _}: props) => React.int(x + y)
+}
+```
+
+
+
+This feature can be used when the nominally different components are passed to the prop of `Screen` component in [ReScript React Native Navigation](https://github.com/rescript-react-native/rescript-react-navigation).
+
+```res
+type screenProps = { navigation: navigation, route: route }
+
+module Screen: {
+ @react.component
+ let make: (
+ ~name: string,
+ ~component: React.component,
+ ...
+ ) => React.element
+}
+
+
+
+```
+
+This example cann't pass the type checker, because the props types of both components are nominally different. You can make the both components having the same props type by passing `screenProps` type as argument to `@react.component`.
+
+```res
+module A = {
+ @react.component(:screenProps)
+ let make = (
+ ~navigation: navigation,
+ ~route: route
+ ) => ...
+}
+
+module B = {
+ @react.component(:screenProps)
+ let make = (
+ ~navigation: navigation,
+ ~route: route
+ ) => ...
+}
+```
\ No newline at end of file
diff --git a/pages/docs/react/v0.11.0/forwarding-refs.mdx b/pages/docs/react/v0.11.0/forwarding-refs.mdx
new file mode 100644
index 000000000..b1fe51949
--- /dev/null
+++ b/pages/docs/react/v0.11.0/forwarding-refs.mdx
@@ -0,0 +1,188 @@
+---
+title: Forwarding Refs
+description: "Forwarding Ref values in ReScript and React"
+canonical: "/docs/react/latest/forwarding-refs"
+---
+
+# Forwarding Refs
+
+
+
+Ref forwarding is a technique for automatically passing a [React.ref](./refs-and-the-dom) through a component to one of its children. This is typically not necessary for most components in the application. However, it can be useful for some kinds of components, especially in reusable component libraries. The most common scenarios are described below.
+
+
+
+## Why Ref Forwarding?
+
+Consider a FancyButton component that renders the native button DOM element:
+
+```res
+// FancyButton.res
+
+@react.component
+let make = (~children) => {
+
+}
+```
+
+React components hide their implementation details, including their rendered output. Other components using FancyButton **usually will not need** to obtain a ref to the inner button DOM element. This is good because it prevents components from relying on each other’s DOM structure too much.
+
+Although such encapsulation is desirable for application-level components like `FeedStory` or `Comment`, it can be inconvenient for highly reusable “leaf” components like `FancyButton` or `MyTextInput`. These components tend to be used throughout the application in a similar manner as a regular DOM button and input, and accessing their DOM nodes may be unavoidable for managing focus, selection, or animations.
+
+There are currently two strategies on forwarding refs through a component. In ReScript and React we strongly recommend **passing your ref as a prop**, but there is also a dedicated API called `React.forwardRef`.
+
+We will discuss both methods in this document.
+
+## Forward Refs via Props
+
+A `React.ref` can be passed down like any other prop. The component will take care of forwarding the ref to the right DOM element.
+
+**No new concepts to learn!**
+
+In the example below, `FancyInput` defines a prop `inputRef` that will be forwarded to its `input` element:
+
+```res
+// App.res
+
+module FancyInput = {
+ @react.component
+ let make = (~children, ~inputRef: ReactDOM.domRef) =>
+
children
+}
+
+@send external focus: Dom.element => unit = "focus"
+
+@react.component
+let make = () => {
+ let input = React.useRef(Js.Nullable.null)
+
+ let focusInput = () =>
+ input.current
+ ->Js.Nullable.toOption
+ ->Belt.Option.forEach(input => input->focus)
+
+ let onClick = _ => focusInput()
+
+
+
+
+
+
+}
+```
+
+We use the `ReactDOM.domRef` type to represent our `inputRef`. We pass our ref in the exact same manner as we'd do a DOM `ref` attribute (``).
+
+
+## [Discouraged] React.forwardRef
+
+**Note:** We discourage this method since it [will likely go away](https://twitter.com/dan_abramov/status/1173372190395445251) at some point, and doesn't yield any obvious advantages over the previously mentioned ref prop passing.
+
+`React.forwardRef` offers a way to "emulate a `ref` prop" within custom components. Internally the component will forward the passed `ref` value to the target DOM element instead.
+
+This is how the previous example would look like with the `React.forwardRef` approach:
+
+
+
+```res
+// App.res
+
+module FancyInput = {
+ @react.component
+ let make = React.forwardRef((~className=?, ~children, ref) =>
+
+ Belt.Option.map(ReactDOM.Ref.domRef)}
+ />
+ children
+
+ )
+}
+
+@send external focus: Dom.element => unit = "focus"
+
+@react.component
+let make = () => {
+ let input = React.useRef(Js.Nullable.null)
+
+ let focusInput = () =>
+ input.current->Js.Nullable.toOption->Belt.Option.forEach(input => input->focus)
+
+ let onClick = _ => focusInput()
+
+
+
+
+
+
+}
+```
+
+```js
+import * as React from "react";
+import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
+import * as Caml_option from "rescript/lib/es6/caml_option.js";
+
+var make = React.forwardRef(function (props, ref) {
+ return React.createElement(
+ "div",
+ undefined,
+ React.createElement("input", {
+ ref: Belt_Option.map(
+ ref == null ? undefined : Caml_option.some(ref),
+ function (prim) {
+ return prim;
+ }
+ ),
+ className: props.className,
+ type: "text",
+ }),
+ props.children
+ );
+});
+
+var FancyInput = {
+ make: make,
+};
+
+function App(props) {
+ var input = React.useRef(null);
+ var onClick = function (param) {
+ Belt_Option.forEach(
+ Caml_option.nullable_to_opt(input.current),
+ function (input) {
+ input.focus();
+ }
+ );
+ };
+ return React.createElement(
+ "div",
+ undefined,
+ React.createElement(make, {
+ className: "fancy",
+ children: React.createElement(
+ "button",
+ {
+ onClick: onClick,
+ },
+ "Click to focus"
+ ),
+ ref: input,
+ })
+ );
+}
+```
+
+
+
+**Note:** Our `@react.component` decorator transforms our labeled argument props within our `React.forwardRef` function in the same manner as our classic `make` function.
+
+This way, components using `FancyInput` can get a ref to the underlying `input` DOM node and access it if necessary—just like if they used a DOM `input` directly.
+
+## Note for Component Library Maintainers
+
+**When you start using ref forwarding in a component library, you should treat it as a breaking change and release a new major version of your library**. This is because your library likely has an observably different behavior (such as what refs get assigned to, and what types are exported), and this can break apps and other libraries that depend on the old behavior.
diff --git a/pages/docs/react/v0.11.0/hooks-context.mdx b/pages/docs/react/v0.11.0/hooks-context.mdx
new file mode 100644
index 000000000..8af68ddfe
--- /dev/null
+++ b/pages/docs/react/v0.11.0/hooks-context.mdx
@@ -0,0 +1,137 @@
+---
+title: useContext Hook
+description: "Details about the useContext React hook in ReScript"
+canonical: "/docs/react/latest/hooks-context"
+---
+
+# useContext
+
+
+
+Context provides a way to pass data through the component tree without having to pass props down manually at every level. The `useContext` hooks gives access to such Context values.
+
+
+
+> **Note:** All the details and rationale on React's context feature can be found in [here](./context).
+
+## Usage
+
+```res
+let value = React.useContext(myContext)
+```
+
+Accepts a `React.Context.t` (the value returned from `React.createContext`) and returns the current context value for that context. The current context value is determined by the value prop of the nearest `` above the calling component in the tree.
+
+
+## Examples
+
+### A Simple ThemeProvider
+
+
+
+
+```res
+// App.res
+module ThemeContext = {
+ let context = React.createContext("light")
+
+ module Provider = {
+ let make = React.Context.provider(context)
+ }
+}
+
+module ThemedButton = {
+ @react.component
+ let make = () => {
+ let theme = React.useContext(ThemeContext.context)
+ let (color, backgroundColor) = switch theme {
+ | "dark" => ("#ffffff", "#222222")
+ | "light" | _ => ("#000000", "#eeeeee")
+ }
+
+ let style = ReactDOMStyle.make(~color, ~backgroundColor, ())
+
+
+ }
+}
+
+module Toolbar = {
+ @react.component
+ let make = () => {
+
+
+}
+```
+```js
+var context = React.createContext("light");
+
+var make = context.Provider;
+
+var Provider = {
+ make: make
+};
+
+var ThemeContext = {
+ context: context,
+ Provider: Provider
+};
+
+function App$ThemedButton(props) {
+ var theme = React.useContext(context);
+ var match;
+ switch (theme) {
+ case "dark" :
+ match = [
+ "#ffffff",
+ "#222222"
+ ];
+ break;
+ case "light" :
+ match = [
+ "#000000",
+ "#eeeeee"
+ ];
+ break;
+ default:
+ match = [
+ "#000000",
+ "#eeeeee"
+ ];
+ }
+ var style = {
+ backgroundColor: match[1],
+ color: match[0]
+ };
+ return React.createElement("button", {
+ style: style
+ }, "I am a styled button!");
+}
+
+var ThemedButton = {
+ make: App$ThemedButton
+};
+
+function App$Toolbar(props) {
+ return React.createElement("div", undefined, React.createElement(App$ThemedButton, {}));
+}
+
+var Toolbar = {
+ make: App$Toolbar
+};
+
+function App(props) {
+ return React.createElement(make, {
+ value: "dark",
+ children: React.createElement("div", undefined, React.createElement(App$Toolbar, {}))
+ });
+}
+```
+
+
diff --git a/pages/docs/react/v0.11.0/hooks-custom.mdx b/pages/docs/react/v0.11.0/hooks-custom.mdx
new file mode 100644
index 000000000..42a1eac02
--- /dev/null
+++ b/pages/docs/react/v0.11.0/hooks-custom.mdx
@@ -0,0 +1,537 @@
+---
+title: Build A Custom Hook
+description: "How to build your own hooks in ReScript & React"
+canonical: "/docs/react/latest/hooks-custom"
+---
+
+# Build A Custom Hook
+
+
+
+React comes with a few fundamental hooks out-of-the-box, such as `React.useState` or `React.useEffect`. Here you will learn how to build your own, higher-level hooks for your React use-cases.
+
+
+
+## Why Custom Hooks?
+
+Custom hooks let you extract existing component logic into reusable, separate functions.
+
+Let's go back to a previous example from our [React.useEffect section](./hooks-effect) where we built a component for a chat application that displays a message, indicating whether a friend is online or offline:
+
+
+
+```res {16-31}
+// FriendStatus.res
+
+module ChatAPI = {
+ // Imaginary globally available ChatAPI for demo purposes
+ type status = { isOnline: bool };
+ @val external subscribeToFriendStatus: (string, status => unit) => unit = "subscribeToFriendStatus";
+ @val external unsubscribeFromFriendStatus: (string, status => unit) => unit = "unsubscribeFromFriendStatus";
+}
+
+type state = Offline | Loading | Online;
+
+@react.component
+let make = (~friendId: string) => {
+ let (state, setState) = React.useState(_ => Offline)
+
+ React.useEffect(() => {
+ let handleStatusChange = (status) => {
+ setState(_ => {
+ status.ChatAPI.isOnline ? Online : Offline
+ })
+ }
+
+ ChatAPI.subscribeToFriendStatus(friendId, handleStatusChange);
+ setState(_ => Loading);
+
+ let cleanup = () => {
+ ChatAPI.unsubscribeFromFriendStatus(friendId, handleStatusChange)
+ }
+
+ Some(cleanup)
+ })
+
+ let text = switch(state) {
+ | Offline => friendId ++ " is offline"
+ | Online => friendId ++ " is online"
+ | Loading => "loading..."
+ }
+
+
+ {React.string(text)}
+
+}
+
+```
+
+```js
+function FriendStatus(Props) {
+ var friendId = Props.friendId;
+ var match = React.useState(function () {
+ return /* Offline */0;
+ });
+ var setState = match[1];
+ React.useEffect(function () {
+ var handleStatusChange = function (status) {
+ return Curry._1(setState, (function (param) {
+ if (status.isOnline) {
+ return /* Online */2;
+ } else {
+ return /* Offline */0;
+ }
+ }));
+ };
+ subscribeToFriendStatus(friendId, handleStatusChange);
+ Curry._1(setState, (function (param) {
+ return /* Loading */1;
+ }));
+ return (function (param) {
+ unsubscribeFromFriendStatus(friendId, handleStatusChange);
+
+ });
+ });
+ var text;
+ switch (match[0]) {
+ case /* Offline */0 :
+ text = friendId + " is offline";
+ break;
+ case /* Loading */1 :
+ text = "loading...";
+ break;
+ case /* Online */2 :
+ text = friendId + " is online";
+ break;
+
+ }
+ return React.createElement("div", undefined, text);
+}
+```
+
+
+
+Now let’s say that our chat application also has a contact list, and we want to render names of online users with a green color. We could copy and paste similar logic above into our `FriendListItem` component but it wouldn’t be ideal:
+
+
+
+```res {15-30}
+// FriendListItem.res
+type state = Offline | Loading | Online;
+
+// module ChatAPI = {...}
+
+type friend = {
+ id: string,
+ name: string
+};
+
+@react.component
+let make = (~friend: friend) => {
+ let (state, setState) = React.useState(_ => Offline)
+
+ React.useEffect(() => {
+ let handleStatusChange = (status) => {
+ setState(_ => {
+ status.ChatAPI.isOnline ? Online : Offline
+ })
+ }
+
+ ChatAPI.subscribeToFriendStatus(friend.id, handleStatusChange);
+ setState(_ => Loading);
+
+ let cleanup = () => {
+ ChatAPI.unsubscribeFromFriendStatus(friend.id, handleStatusChange)
+ }
+
+ Some(cleanup)
+ })
+
+ let color = switch(state) {
+ | Offline => "red"
+ | Online => "green"
+ | Loading => "grey"
+ }
+
+
+ {React.string(friend.name)}
+
+}
+```
+
+```js
+function FriendListItem(Props) {
+ var friend = Props.friend;
+ var match = React.useState(function () {
+ return /* Offline */0;
+ });
+ var setState = match[1];
+ React.useEffect(function () {
+ var handleStatusChange = function (status) {
+ return Curry._1(setState, (function (param) {
+ if (status.isOnline) {
+ return /* Online */2;
+ } else {
+ return /* Offline */0;
+ }
+ }));
+ };
+ subscribeToFriendStatus(friend.id, handleStatusChange);
+ Curry._1(setState, (function (param) {
+ return /* Loading */1;
+ }));
+ return (function (param) {
+ unsubscribeFromFriendStatus(friend.id, handleStatusChange);
+
+ });
+ });
+ var color;
+ switch (match[0]) {
+ case /* Offline */0 :
+ color = "red";
+ break;
+ case /* Loading */1 :
+ color = "grey";
+ break;
+ case /* Online */2 :
+ color = "green";
+ break;
+
+ }
+ return React.createElement("li", {
+ style: {
+ color: color
+ }
+ }, friend.name);
+}
+```
+
+
+
+Instead, we’d like to share this logic between `FriendStatus` and `FriendListItem`.
+
+Traditionally in React, we’ve had two popular ways to share stateful logic between components: render props and higher-order components. We will now look at how Hooks solve many of the same problems without forcing you to add more components to the tree.
+
+## Extracting a Custom Hook
+
+Usually when we want to share logic between two functions, we extract it to a third function. Both components and Hooks are functions, so this works for them too!
+
+**A custom Hook is a function whose name starts with ”use” and that may call other Hooks.** For example, `useFriendStatus` below is our first custom Hook (we create a new file `FriendStatusHook.res` to encapsulate the `state` type as well):
+
+
+
+
+
+```res
+// FriendStatusHook.res
+
+// module ChatAPI {...}
+
+type state = Offline | Loading | Online
+
+let useFriendStatus = (friendId: string): state => {
+ let (state, setState) = React.useState(_ => Offline)
+
+ React.useEffect(() => {
+ let handleStatusChange = status => {
+ setState(_ => {
+ status.ChatAPI.isOnline ? Online : Offline
+ })
+ }
+
+ ChatAPI.subscribeToFriendStatus(friendId, handleStatusChange)
+ setState(_ => Loading)
+
+ let cleanup = () => {
+ ChatAPI.unsubscribeFromFriendStatus(friendId, handleStatusChange)
+ }
+
+ Some(cleanup)
+ })
+
+ state
+}
+```
+
+```js
+function useFriendStatus(friendId) {
+ var match = React.useState(function () {
+ return /* Offline */0;
+ });
+ var setState = match[1];
+ React.useEffect(function () {
+ var handleStatusChange = function (status) {
+ return Curry._1(setState, (function (param) {
+ if (status.isOnline) {
+ return /* Online */2;
+ } else {
+ return /* Offline */0;
+ }
+ }));
+ };
+ subscribeToFriendStatus(friendId, handleStatusChange);
+ Curry._1(setState, (function (param) {
+ return /* Loading */1;
+ }));
+ return (function (param) {
+ unsubscribeFromFriendStatus(friendId, handleStatusChange);
+
+ });
+ });
+ return match[0];
+}
+```
+
+
+
+There’s nothing new inside of it — the logic is copied from the components above. Just like in a component, make sure to only call other Hooks unconditionally at the top level of your custom Hook.
+
+Unlike a React component, a custom Hook doesn’t need to have a specific signature. We can decide what it takes as arguments, and what, if anything, it should return. In other words, it’s just like a normal function. Its name should always start with use so that you can tell at a glance that the rules of Hooks apply to it.
+
+The purpose of our `useFriendStatus` Hook is to subscribe us to a friend’s status. This is why it takes `friendId` as an argument, and returns the online state like `Online`, `Offline` or `Loading`:
+
+```res
+let useFriendStatus = (friendId: string): status {
+ let (state, setState) = React.useState(_ => Offline);
+
+ // ...
+
+ state
+}
+```
+
+Now let’s use our custom Hook.
+
+
+## Using a Custom Hook
+
+In the beginning, our stated goal was to remove the duplicated logic from the `FriendStatus` and `FriendListItem` components. Both of them want to know the online state of a friend.
+
+
+Now that we’ve extracted this logic to a useFriendStatus hook, we can just use it:
+
+
+
+
+```res {6}
+// FriendStatus.res
+type friend = { id: string };
+
+@react.component
+let make = (~friend: friend) => {
+ let onlineState = FriendStatusHook.useFriendStatus(friend.id);
+
+ let status = switch(onlineState) {
+ | FriendStatusHook.Online => "Online"
+ | Loading => "Loading"
+ | Offline => "Offline"
+ }
+
+ React.string(status);
+}
+```
+```js
+function FriendStatus(Props) {
+ var friend = Props.friend;
+ var onlineState = useFriendStatus(friend.id);
+ var color;
+ switch (onlineState) {
+ case /* Offline */0 :
+ color = "red";
+ break;
+ case /* Loading */1 :
+ color = "grey";
+ break;
+ case /* Online */2 :
+ color = "green";
+ break;
+
+ }
+ return React.createElement("li", {
+ style: {
+ color: color
+ }
+ }, friend.name);
+}
+```
+
+
+
+
+
+```res {4}
+// FriendListItem.res
+@react.component
+let make = (~friend: friend) => {
+ let onlineState = FriendStatusHook.useFriendStatus(friend.id);
+
+ let color = switch(onlineState) {
+ | Offline => "red"
+ | Online => "green"
+ | Loading => "grey"
+ }
+
+
+ {React.string(friend.name)}
+
+}
+```
+
+```js
+function FriendListItem(Props) {
+ var friend = Props.friend;
+ var onlineState = useFriendStatus(friend.id);
+ var color;
+ switch (onlineState) {
+ case /* Offline */0 :
+ color = "red";
+ break;
+ case /* Loading */1 :
+ color = "grey";
+ break;
+ case /* Online */2 :
+ color = "green";
+ break;
+
+ }
+ return React.createElement("li", {
+ style: {
+ color: color
+ }
+ }, friend.name);
+}
+```
+
+
+
+
+**Is this code equivalent to the original examples?** Yes, it works in exactly the same way. If you look closely, you’ll notice we didn’t make any changes to the behavior. All we did was to extract some common code between two functions into a separate function. Custom Hooks are a convention that naturally follows from the design of Hooks, rather than a React feature.
+
+**Do I have to name my custom Hooks starting with “use”?** Please do. This convention is very important. Without it, we wouldn’t be able to automatically check for violations of rules of Hooks because we couldn’t tell if a certain function contains calls to Hooks inside of it.
+
+**Do two components using the same Hook share state?** No. Custom Hooks are a mechanism to reuse stateful logic (such as setting up a subscription and remembering the current value), but every time you use a custom Hook, all state and effects inside of it are fully isolated.
+
+**How does a custom Hook get isolated state?** Each call to a Hook gets isolated state. Because we call useFriendStatus directly, from React’s point of view our component just calls useState and useEffect. And as we learned earlier, we can call useState and useEffect many times in one component, and they will be completely independent.
+
+
+### Tip: Pass Information Between Hooks
+
+Since Hooks are functions, we can pass information between them.
+
+To illustrate this, we’ll use another component from our hypothetical chat example. This is a chat message recipient picker that displays whether the currently selected friend is online:
+
+
+
+```res {11,12,14-18,22}
+type friend = {id: string, name: string}
+
+let friendList = [
+ {id: "1", name: "Phoebe"},
+ {id: "2", name: "Rachel"},
+ {id: "3", name: "Ross"},
+]
+
+@react.component
+let make = () => {
+ let (recipientId, setRecipientId) = React.useState(_ => "1")
+ let recipientOnlineState = FriendStatusHook.useFriendStatus(recipientId)
+
+ let color = switch recipientOnlineState {
+ | FriendStatusHook.Offline => Circle.Red
+ | Online => Green
+ | Loading => Grey
+ }
+
+ let onChange = evt => {
+ let value = ReactEvent.Form.target(evt)["value"]
+ setRecipientId(value)
+ }
+
+ let friends = Belt.Array.map(friendList, friend => {
+
+ })
+
+ <>
+
+
+ >
+}
+```
+```js
+var friendList = [
+ {
+ id: "1",
+ name: "Phoebe"
+ },
+ {
+ id: "2",
+ name: "Rachel"
+ },
+ {
+ id: "3",
+ name: "Ross"
+ }
+];
+
+function Playground(Props) {
+ var match = React.useState(function () {
+ return "1";
+ });
+ var setRecipientId = match[1];
+ var recipientId = match[0];
+ var recipientOnlineState = useFriendStatus(recipientId);
+ var color;
+ switch (recipientOnlineState) {
+ case /* Offline */0 :
+ color = /* Red */0;
+ break;
+ case /* Loading */1 :
+ color = /* Grey */2;
+ break;
+ case /* Online */2 :
+ color = /* Green */1;
+ break;
+
+ }
+ var onChange = function (evt) {
+ return Curry._1(setRecipientId, evt.target.value);
+ };
+ var friends = Belt_Array.map(friendList, (function (friend) {
+ return React.createElement("option", {
+ key: friend.id,
+ value: friend.id
+ }, friend.name);
+ }));
+ return React.createElement(React.Fragment, undefined, React.createElement(Playground$Circle, {
+ color: color
+ }), React.createElement("select", {
+ value: recipientId,
+ onChange: onChange
+ }, friends));
+}
+```
+
+
+
+We keep the currently chosen friend ID in the `recipientId` state variable, and update it if the user chooses a different friend in the `