Skip to content

Commit 2700073

Browse files
committed
Add context doc
1 parent 0b727e9 commit 2700073

File tree

1 file changed

+208
-0
lines changed

1 file changed

+208
-0
lines changed

pages/docs/react/latest/context.mdx

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
---
2+
title: Context
3+
description: "Details about Context in ReScript and React"
4+
canonical: "/docs/react/latest/context"
5+
category: "Main Concepts"
6+
---
7+
8+
# Context
9+
10+
<Intro>
11+
12+
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
13+
14+
</Intro>
15+
16+
## Why Context?
17+
18+
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.
19+
20+
**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!
21+
22+
23+
## When to Use Context
24+
25+
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:
26+
27+
<CodeTab labels={["ReScript", "JS Output"]}>
28+
29+
```res
30+
// src/App.res
31+
type theme = Light | Dark;
32+
33+
module Button = {
34+
@react.component
35+
let make = (~theme) => {
36+
let className = switch theme {
37+
| Light => "theme-light"
38+
| Dark => "theme-black"
39+
};
40+
<button className> {React.string("Click me")} </button>
41+
}
42+
}
43+
44+
module ThemedButton = {
45+
@react.component
46+
let make = (~theme) => {
47+
<Button theme />
48+
}
49+
}
50+
51+
module Toolbar = {
52+
@react.component
53+
let make = (~theme) => {
54+
<div>
55+
<ThemedButton theme/>
56+
</div>
57+
}
58+
}
59+
60+
@react.component
61+
let make = () => {
62+
// We define the theme in the
63+
// toplevel App component and
64+
// pass it down
65+
<Toolbar theme=Dark/>
66+
}
67+
```
68+
69+
```js
70+
function Button(Props) {
71+
var theme = Props.theme;
72+
var className = theme ? "theme-black" : "theme-light";
73+
return React.createElement("button", {
74+
className: className
75+
}, "Click me");
76+
}
77+
78+
function ThemedButton(Props) {
79+
var theme = Props.theme;
80+
return React.createElement(Button, {
81+
theme: theme
82+
});
83+
}
84+
85+
function Toolbar(Props) {
86+
var theme = Props.theme;
87+
return React.createElement("div", undefined, React.createElement(ThemedButton, {
88+
theme: theme
89+
}));
90+
}
91+
92+
function Playground(Props) {
93+
return React.createElement(Toolbar, {
94+
theme: /* Dark */1
95+
});
96+
}
97+
```
98+
</CodeTab>
99+
100+
Using context, we can avoid passing props through intermediate elements:
101+
102+
<CodeTab labels={["ReScript", "JS Output"]}>
103+
104+
```res
105+
// src/App.res
106+
107+
module ThemeContext = {
108+
type theme = Light | Dark;
109+
let context = React.createContext(Light)
110+
111+
module Provider = {
112+
let provider = React.Context.provider(context)
113+
114+
@react.component
115+
let make = (~value, ~children) => {
116+
React.createElement(provider, {"value": value, "children": children})
117+
}
118+
}
119+
}
120+
121+
module Button = {
122+
@react.component
123+
let make = (~theme) => {
124+
let className = switch theme {
125+
| ThemeContext.Light => "theme-light"
126+
| Dark => "theme-black"
127+
};
128+
<button className> {React.string("Click me")} </button>
129+
}
130+
}
131+
132+
module ThemedButton = {
133+
@react.component
134+
let make = () => {
135+
let theme = React.useContext(ThemeContext.context)
136+
137+
<Button theme/>
138+
}
139+
}
140+
141+
module Toolbar = {
142+
@react.component
143+
let make = () => {
144+
<div> <ThemedButton /> </div>
145+
}
146+
}
147+
148+
@react.component
149+
let make = () => {
150+
<ThemeContext.Provider value=ThemeContext.Dark>
151+
<div> <Toolbar /> </div>
152+
</ThemeContext.Provider>
153+
}
154+
```
155+
```js
156+
var context = React.createContext(/* Light */0);
157+
158+
var provider = context.Provider;
159+
160+
function ThemeContext$Provider(Props) {
161+
var value = Props.value;
162+
var children = Props.children;
163+
return React.createElement(provider, {
164+
value: value,
165+
children: children
166+
});
167+
}
168+
169+
function Button(Props) {
170+
var theme = Props.theme;
171+
var className = theme ? "theme-black" : "theme-light";
172+
return React.createElement("button", {
173+
className: className
174+
}, "Click me");
175+
}
176+
177+
var Button = {
178+
make: Button
179+
};
180+
181+
function ThemedButton(Props) {
182+
var theme = React.useContext(context);
183+
return React.createElement(Button, {
184+
theme: theme
185+
});
186+
}
187+
188+
var ThemedButton = {
189+
make: ThemedButton
190+
};
191+
192+
function Toolbar(Props) {
193+
return React.createElement("div", undefined, React.createElement(ThemedButton, {}));
194+
}
195+
196+
var Toolbar = {
197+
make: Toolbar
198+
};
199+
200+
function Playground(Props) {
201+
return React.createElement(ThemeContext$Provider, {
202+
value: /* Dark */1,
203+
children: React.createElement("div", undefined, React.createElement(Toolbar, {}))
204+
});
205+
}
206+
```
207+
208+
</CodeTab>

0 commit comments

Comments
 (0)