Context
We understand what a Context
is, a place that gives us a way to pass values to child components without passing them to child props.
Normally when transferring data between components, we usually put them into component props, this will lead to some components will have very bulky props and many components have the same props and to solve this problem, We have a way of using Context
When to Use Context
The theory is so but we can not use Context to transfer all data. So we will use Context to transfer the data like.
Context is designed to share data between components, the type of data shared through the Context is usually the type of “Global” nature that is common to many components, such as user information, themes, languages.
We will start with an example with the theme.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">React <span class="token punctuation">.</span> Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token operator"><</span> Toolbar theme <span class="token operator">=</span> <span class="token string">"dark"</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">Toolbar</span> <span class="token punctuation">(</span> props <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// The Toolbar component must take an extra "theme" prop</span> <span class="token comment">// and pass it to the ThemedButton. This can become painful</span> <span class="token comment">// if every single button in the app needs to know the theme</span> <span class="token comment">// because it would have to be passed through all components.</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> div <span class="token operator">></span> <span class="token operator"><</span> ThemedButton theme <span class="token operator">=</span> <span class="token punctuation">{</span> props <span class="token punctuation">.</span> theme <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">ThemedButton</span> <span class="token keyword">extends</span> <span class="token class-name">React <span class="token punctuation">.</span> Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token operator"><</span> Button theme <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> props <span class="token punctuation">.</span> theme <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
With the above example, to use the theme, we will have to put the theme in the props of the component and you try to imagine if the entire app uses so, the theme={props.theme}
will be repeated how many times.
As for Context we will use the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <span class="token comment">// Context lets us pass a value deep into the component tree</span> <span class="token comment">// without explicitly threading it through every component.</span> <span class="token comment">// Create a context for the current theme (with "light" as the default).</span> <span class="token keyword">const</span> ThemeContext <span class="token operator">=</span> React <span class="token punctuation">.</span> <span class="token function">createContext</span> <span class="token punctuation">(</span> <span class="token string">'light'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">React <span class="token punctuation">.</span> Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Use a Provider to pass the current theme to the tree below.</span> <span class="token comment">// Any component can read it, no matter how deep it is.</span> <span class="token comment">// In this example, we're passing "dark" as the current value.</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> ThemeContext <span class="token punctuation">.</span> Provider value <span class="token operator">=</span> <span class="token string">"dark"</span> <span class="token operator">></span> <span class="token operator"><</span> Toolbar <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> ThemeContext <span class="token punctuation">.</span> Provider <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// A component in the middle doesn't have to</span> <span class="token comment">// pass the theme down explicitly anymore.</span> <span class="token keyword">function</span> <span class="token function">Toolbar</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> div <span class="token operator">></span> <span class="token operator"><</span> ThemedButton <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">ThemedButton</span> <span class="token keyword">extends</span> <span class="token class-name">React <span class="token punctuation">.</span> Component</span> <span class="token punctuation">{</span> <span class="token comment">// Assign a contextType to read the current theme context.</span> <span class="token comment">// React will find the closest theme Provider above and use its value.</span> <span class="token comment">// In this example, the current theme is "dark".</span> <span class="token keyword">static</span> contextType <span class="token operator">=</span> ThemeContext <span class="token punctuation">;</span> <span class="token function">render</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token operator"><</span> Button theme <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> context <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Before You Use Context
Context is usually used when some data needs to be accessed at many components and at many levels, but we need to be careful and don’t use Context because it will make reuse of components. harder.
If you just want to reduce the load of multiple props between components, then you should consider using component compositions rather than Context.
A simple example is as follows:
1 2 3 4 5 6 7 8 9 10 | <span class="token operator"><</span> Page user <span class="token operator">=</span> <span class="token punctuation">{</span> user <span class="token punctuation">}</span> avatarSize <span class="token operator">=</span> <span class="token punctuation">{</span> avatarSize <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token comment">// ... which renders ...</span> <span class="token operator"><</span> PageLayout user <span class="token operator">=</span> <span class="token punctuation">{</span> user <span class="token punctuation">}</span> avatarSize <span class="token operator">=</span> <span class="token punctuation">{</span> avatarSize <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token comment">// ... which renders ...</span> <span class="token operator"><</span> NavigationBar user <span class="token operator">=</span> <span class="token punctuation">{</span> user <span class="token punctuation">}</span> avatarSize <span class="token operator">=</span> <span class="token punctuation">{</span> avatarSize <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token comment">// ... which renders ...</span> <span class="token operator"><</span> Link href <span class="token operator">=</span> <span class="token punctuation">{</span> user <span class="token punctuation">.</span> permalink <span class="token punctuation">}</span> <span class="token operator">></span> <span class="token operator"><</span> Avatar user <span class="token operator">=</span> <span class="token punctuation">{</span> user <span class="token punctuation">}</span> size <span class="token operator">=</span> <span class="token punctuation">{</span> avatarSize <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> Link <span class="token operator">></span> |
For the above example, you need to pass the user
and avatarSize
down to the last layer and only the last layer uses the two above props, but in the above example, those two props are passed through multiple Component classes and it is redundant, And when the Avata
Component needs some more props, what happens? The props of the other components will balloon a lot while they don’t need to use them.
As mentioned above, we can manipulate the component composition by putting the Avatar
component first and passing it over to the other Components, so that the other Components will not need to care about how the Avatar
will change. just getting a Component Avatar
is enough, but for the Avatar
section, no matter how many props it needs, it won’t affect the other Components.
Inverted ways like this will make your code much cleaner and easier to maintenance
by minimizing the transmission of props, but it’s not a good way in many cases. a little bit more complicated
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token keyword">function</span> <span class="token function">Page</span> <span class="token punctuation">(</span> props <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> user <span class="token operator">=</span> props <span class="token punctuation">.</span> user <span class="token punctuation">;</span> <span class="token keyword">const</span> content <span class="token operator">=</span> <span class="token operator"><</span> Feed user <span class="token operator">=</span> <span class="token punctuation">{</span> user <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">;</span> <span class="token keyword">const</span> topBar <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token operator"><</span> NavigationBar <span class="token operator">></span> <span class="token operator"><</span> Link href <span class="token operator">=</span> <span class="token punctuation">{</span> user <span class="token punctuation">.</span> permalink <span class="token punctuation">}</span> <span class="token operator">></span> <span class="token operator"><</span> Avatar user <span class="token operator">=</span> <span class="token punctuation">{</span> user <span class="token punctuation">}</span> size <span class="token operator">=</span> <span class="token punctuation">{</span> props <span class="token punctuation">.</span> avatarSize <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> Link <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> NavigationBar <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> PageLayout topBar <span class="token operator">=</span> <span class="token punctuation">{</span> topBar <span class="token punctuation">}</span> content <span class="token operator">=</span> <span class="token punctuation">{</span> content <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
You can see we can not limit a component to only 1 child component, but it can transmit multiple child components at once or multiple views here . This is an example of splitting a component into many components right in the parent component, if you want to communicate with the parent component (using methods, state, props of the parent component), then you can use the Render Props .
However, in reality, it is not as simple as the examples we have just seen, but it will be much more complicated, such as sharing data not only in the Father and Son Component, but must be shared at many other levels. many, between many peer components. And the Context can help the components can use the same data, if the data in the Context changes, the components will change.
Today we stop at what Context is and when to use it, the following article will talk about how to use dentists.