Reactコンテキストを5分で学ぶ-初心者向けチュートリアル

ReactのContextAPIは、多くの場合、Reduxに完全に取って代わる、状態管理ツールとして選択されるようになりました。この5分間の簡単なチュートリアルでは、コンテキストとは何か、およびその使用方法の概要を説明します。

このテーマの適切な紹介が必要な場合は、次の高度なReactコースの順番待ちリストに参加できます。まだ初心者の場合は、Reactに関する無料の入門コースを確認してください。

下のボックスが個別のコンポーネントを表すこのツリーについて考えてみます。

コンポーネントツリー

下部のコンポーネントに状態を簡単に追加できますが、これまで、コンポーネントの兄弟にデータを渡す唯一の方法は、状態を上位のコンポーネントに移動してから、小道具を介して兄弟に戻すことでした。

小道具を介してデータを渡す

後で、状態のあるコンポーネントの兄弟にもデータが必要であることがわかった場合は、状態を再度持ち上げて、元に戻す必要があります。

複数のレベルを介して状態を渡す

このソリューションは機能しますが、別のブランチのコンポーネントがデータを必要とする場合に問題が発生します。

より遠いコンポーネントにはデータが必要です

この場合、中間レベルではデータが必要ない場合でも、アプリケーションの最上位からすべての中間コンポーネントを経由して、最下位のデータが必要なコンポーネントに状態を渡す必要があります。この退屈で時間のかかるプロセスは、プロップドリルとして知られてます。

小道具の掘削

そこで、Context APIが登場します。これは、すべてのレベルで小道具を渡すことなく、プロバイダーとコンシューマーのペアを介してコンポーネントツリーを介してデータを渡す方法を提供します。これは、Catch with dataを再生するコンポーネントと考えてください。中間コンポーネントは、何かが起こっていることを「認識」していない可能性があります。

実行中のコンテキスト

これを実証するために、このファンキーな(そして非常に便利な)昼から夜への切り替え画像を作成します。

完全なコードを確認したい場合は、この記事のScrimbaプレイグラウンドを確認してください。

コンテキストの作成

まず、新しいコンテキストを作成します。アプリ全体がこれにアクセスできるようにするため、に移動しindex.jsてアプリをでラップしThemeContext.Providerます。

また、value小道具をプロバイダーに渡します。これは、保存したいデータを保持します。今のところ、をハードコーディングするだけ'Day'です。

import React from "react"; import ReactDOM from "react-dom"; import ThemeContext from "./themeContext"; import App from "./App"; ReactDOM.render(   , document.getElementById("root") ); 

contextTypeでコンテキストを消費する

現在、ではApp.js、単にコンポーネントを返しています。

import React from "react"; import Image from "./Image"; class App extends React.Component { render() { return ( ); } } export default App; 

私たちの目標は、レンダリングする画像に応じて、Contextを使用してclassNamesをImage.jsからDayに切り替えるNightことです。これを行うには、呼び出されたコンポーネントに静的プロパティを追加し、ContextType文字列補間を使用してコンポーネントのclassNamesに追加します。

これで、classNamesにはvalue小道具からの文字列が含まれます。注:ThemeContextバグを防ぐために、独自のファイルに移動しました。

import React from "react"; import Button from "./Button"; import ThemeContext from "./themeContext"; class Image extends React.Component { render() { const theme = this.context; return ( ); } } Image.contextType = ThemeContext; export default Image; 

Context.Consumer

残念ながら、このアプローチはクラスベースのコンポーネントでのみ機能します。Hooks in Reactについてすでに学んだことがあれば、最近では機能コンポーネントを使ってほぼ何でもできることをご存知でしょう。したがって、適切な方法として、コンポーネントを機能コンポーネントに変換してから、コンポーネントを使用ThemeContext.Consumerしてアプリを介して情報を渡す必要があります。

これは、要素をそのインスタンス内およびその内部(移動children先)でラップし、要素を返す関数を提供することによって行われます。これは、レンダリングするJSXを返す子として通常の関数を提供する「renderprop」パターンを使用します。

import React from "react"; import Button from "./Button"; import ThemeContext from "./themeContext"; function Image(props) { // We don't need this anymore // const theme = this.context return (  {theme => ( )}  ); } // We don't need this anymore // Image.contextType = ThemeContext; export default Image; 

注:コンポーネントをラップする必要もあります。これにより、後でボタンに機能を追加できます。

import React from "react"; import ThemeContext from "./themeContext"; function Button(props) { return (  {context => (  Switch  ?   ?   )}  ); } export default Button; 

コンテキストプロバイダーの抽出

We are currently passing a hard-coded value down through the Provider, however, our goal is to switch between night and day with our button.

This requires moving our Provider to a separate file and putting it in its own component, in this case, called ThemeContextProvider.

import React, { Component } from "react"; const { Provider, Consumer } = React.createContext(); class ThemeContextProvider extends Component { render() { return {this.props.children}; } } export { ThemeContextProvider, Consumer as ThemeContextConsumer }; 

Note: the value property is now being handled in the new file ThemeContext.js, and should, therefore, be removed from index.js.

Changing Context

To wire up the button, we first add state to ThemeContextProvider:

import React, { Component } from "react"; const { Provider, Consumer } = React.createContext(); // Note: You could also use hooks to provide state and convert this into a functional component. class ThemeContextProvider extends Component { state = { theme: "Day" }; render() { return {this.props.children}; } } export { ThemeContextProvider, Consumer as ThemeContextConsumer }; 

Next, we add a method for switching between day and night:

toggleTheme = () => { this.setState(prevState => { return { theme: prevState.theme === "Day" ? "Night" : "Day" }; }); }; 

Now we change our value property to this.state.theme so that it returns the info from state.

 render() { return {this.props.children}; } } 

Next, we change value to an object containing {theme: this.state.theme, toggleTheme: this.toggleTheme}, and update all the places where we use a single value to look for theme in an object. This means that every theme becomes context and every reference to theme as value becomes context.theme.

Finally, we tell the button to listen for the onClick event and then fire context.toggleTheme - this updates the Consumers which are using the state from the Provider. The code for the button looks like this:

import React from "react"; import { ThemeContextConsumer } from "./themeContext"; function Button(props) { return (  {context => (  Switch  ?   ?   )}  ); } export default Button; 

Our button now switches the image between night and day in one click!

Context caveats

Like all good things in code, there are some caveats to using Context:

  • Don't use Context to avoid drilling props down just one or two layers. Context is great for managing state which is needed by large portions of an application. However, prop drilling is faster if you are just passing info down a couple of layers.

  • Avoid using Context to save state that should be kept locally. So if you need to save a user's form inputs, for example, use local state and not Context.

  • Always wrap the Provider around the lowest possible common parent in the tree - not the app's highest-level component. No need for overkill.

  • Lastly, if you pass an object as your value prop, monitor performance and refactor as necessary. This probably won't be needed unless a drop in performance is noticeable.

Wrap up

この例は非常に単純で、アプリに状態を設定して小道具を介して渡す方がおそらく簡単です。ただし、ツリー内の上位のコンポーネントとは関係なくデータにアクセスできるコンシューマーを持つことの力を示していることを願っています。

React ContextおよびReactの他の優れた機能の詳細については、次の高度なReactコースの順番待ちリストに参加できます。または、より初心者に優しいものを探している場合は、Reactに関する私の無料の入門コースをチェックしてください。

ハッピーコーディング:)