{"id":15416682,"url":"https://github.com/bunlong/react-in-practice","last_synced_at":"2025-04-19T14:33:22.890Z","repository":{"id":72263624,"uuid":"155693660","full_name":"Bunlong/react-in-practice","owner":"Bunlong","description":"Clear examples, explanations, and resources for React v.16.6.x (React Hooks)","archived":false,"fork":false,"pushed_at":"2019-01-15T09:30:15.000Z","size":340,"stargazers_count":11,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T08:43:32.210Z","etag":null,"topics":["react","react-16","react-hook","react-hooks","react-practise","react-suspense","reactjs"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Bunlong.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-01T09:44:33.000Z","updated_at":"2023-08-26T05:13:37.000Z","dependencies_parsed_at":"2023-09-02T05:01:59.135Z","dependency_job_id":null,"html_url":"https://github.com/Bunlong/react-in-practice","commit_stats":{"total_commits":55,"total_committers":1,"mean_commits":55.0,"dds":0.0,"last_synced_commit":"28db82aa26e81c3c8806163f7d9347812510dc00"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bunlong%2Freact-in-practice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bunlong%2Freact-in-practice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bunlong%2Freact-in-practice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bunlong%2Freact-in-practice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Bunlong","download_url":"https://codeload.github.com/Bunlong/react-in-practice/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249715258,"owners_count":21315006,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["react","react-16","react-hook","react-hooks","react-practise","react-suspense","reactjs"],"created_at":"2024-10-01T17:13:24.911Z","updated_at":"2025-04-19T14:33:22.864Z","avatar_url":"https://github.com/Bunlong.png","language":null,"readme":"# React in Practice (React v.16.6.x)\n\n### Table of contents:\n\nHooks\n \n  1. [Introducing](#hooksIntroducing)\n  2. [A Brief of Hook](#hooksBrief)\n      1. [Using the State Hook](./hooks/using_the_state_hook.md \"Using the State Hook\")\n      2. [Using the Effect Hook](./hooks/using_the_effect_hook.md \"Using the Effect Hook\")\n      3. [Building Your Own Hooks](./hooks/building_your_own_hooks.md \"Building Your Own Hooks\")\n      4. [Rules of Hooks](./hooks/rules_of_hooks.md \"Rules of Hooks\")\n      5. [Hooks APIs](./hooks/hooks_apis.md \"Hooks APIs\")\n\nCode-Splitting\n\n  1. [import()](#codeSplittingImport)\n  2. [lazy](#codeSplittingLazy)\n  3. [Suspense](#codeSplittingSuspense)\n  4. [Error boundaries](#codeSplittingErrorBoundaries)\n  5. [Route-based code splitting](#codeSplittingRouteBased)\n  6. [Named Exports](#codeSplittingNamedExports)\n\n[Context](#context)\n\n[React Context API Pattern](#reactContextAPIPattern)\n\nComposition\n\nPortals\n\nmemo\n\n---\n\n## Hooks\n\n### \u003ca name=\"hooksIntroducing\"\u003e\u003c/a\u003e1. Introducing\n\nHooks are a new feature that lets you use state and other React features without writing a class. They're released in React v16.7.0.\n\nHooks are functions that let you \"hook into\" React state and lifecycle features from function components. Hooks don't work inside classes they let you use React without classes.\n\n### \u003ca name=\"hooksBrief\"\u003e\u003c/a\u003e2. A Brief of Hook\n\n**State Hook**\n\nRenders a counter example. When you click the button, it increments the value:\n\nUsing React Hook\n\n```javascript\nimport React, { useState } from 'react';\n\nfunction App() {\n  // Declare a new state variable, which we'll call \"count\"\n  const [count, setCount] = useState(0);\n\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003eYou clicked {count} times\u003c/p\u003e\n      \u003cbutton onClick={() =\u003e setCount(count + 1)}\u003e\n        Click me\n      \u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default App;\n```\n\n- `useState` is a Hook, we call it inside a function component to add some local state to it.\n- `useState` returns a pair: the current state value and a function that lets you update it, you can call this function from an event handler or somewhere else.\n- `useState` has only one argument is the initial state, in the example above 0 is the initial state.\n\nUsing React Class\n\n```javascript\nimport React from 'react';\n\nclass App extends React.Component {\n  state = {\n    count: 0,\n  }\n\n  setCount = () =\u003e {\n    this.setState({\n      count: this.state.count + 1,\n    });\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cp\u003eYou clicked {this.state.count} times\u003c/p\u003e\n        \u003cbutton onClick={() =\u003e this.setCount()}\u003e\n          Click me\n        \u003c/button\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n\nexport default App;\n```\n\nDeclaring multiple state variables.\n\nYou can use State Hook more than once in a single component:\n\n```javascript\nfunction withManyStates() {\n  // Declare multiple state variables!\n  const [name, setName] = useState('Brian');\n  const [age, setAge] = useState(77);\n  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);\n}\n```\n\nReact also provides a few built-in Hooks like `useState`. You can also create custom Hooks to reuse stateful behavior between different components. We'll look at the built-in Hooks first.\n\n\u003e You can learn more about the State Hook on a dedicated page: [Using the State Hook](./hooks/using_the_state_hook.md \"Using the State Hook\").\n\n**Effect Hook**\n\nYou likely performe data fetching, subscriptions, or manually changing the DOM from React components using React lifecycle ( componentDidMount, componentDidUpdate and componentWillUnmount ) in React classes. We call these operations \"side effects\".\n\nThe Effect Hook, `useEffect`, adds the ability to perform side effects from a function component. It serves the same purpose as React lifecycle ( componentDidMount, componentDidUpdate, and componentWillUnmount ) in React classes, but unified into a single API.\n\nExample, this component sets the document title after React updates the DOM:\n\nUsing React Hook\n\n```javascript\nimport React, { useState, useEffect } from 'react';\n\nfunction App() {\n  const [count, setCount] = useState(0);\n\n  // Similar to componentDidMount and componentDidUpdate:\n  useEffect(() =\u003e {\n    // Update the document title using the browser API\n    document.title = `You clicked ${count} times`;\n  });\n\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003eYou clicked {count} times\u003c/p\u003e\n      \u003cbutton onClick={() =\u003e setCount(count + 1)}\u003e\n        Click me\n      \u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default App;\n```\n\n- When you call `useEffect`, you're telling React to run your \"effect\" function after flushing changes to the DOM.\n- Effects are declared inside the component so they have access to its props and state. By default, React runs the effects after every render including the first render.\n\nUsing React Class\n\n```javascript\nimport React from 'react';\n\nclass App extends React.Component {\n  state = {\n    count: 0,\n  }\n\n  componentDidMount() {\n    document.title = `You clicked ${this.state.count} times`;\n  }\n\n  componentDidUpdate() {\n    document.title = `You clicked ${this.state.count} times`;\n    window.addEventListener('resize', this.setCount);\n  }\n\n  setCount = () =\u003e {\n    this.setState({\n      count: this.state.count + 1,\n    });\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cp\u003eYou clicked {this.state.count} times\u003c/p\u003e\n        \u003cbutton onClick={() =\u003e this.setCount()}\u003e\n          Click me\n        \u003c/button\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n\nexport default App;\n```\n\nExample, React would clean up `resize` event when the component unmounts, as well as before re-running the effect due to a subsequent render.\n\nUsing React Hook\n\n```javascript\nimport React, { useState, useEffect } from 'react';\n\nfunction App() {\n  const [width, setWidth] = useState(window.innerWidth);\n\n  // Similar to componentDidMount and componentDidUpdate:\n  useEffect(() =\u003e {\n    const handleResize = () =\u003e setWidth(window.innerWidth);\n    window.addEventListener('resize', handleResize);\n    // Clean up resize event\n    return () =\u003e {\n      window.removeEventListener('resize', handleResize);\n    };\n  });\n\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003eWindow width: {width}\u003c/p\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default App;\n```\n\nUsing React Class\n\n```javascript\nimport React, { Component } from 'react';\n\nclass App extends Component {\n  state = {\n    width: window.innerWidth,\n  }\n\n  UNSAFE_componentWillMount() {\n    window.addEventListener('resize', this.handleResize);\n  }\n\n  componentWillUnmount() {\n    window.removeEventListener('resize', this.handleResize);\n  }\n\n  handleResize = () =\u003e {\n    this.setState({\n      width: window.innerWidth,\n    });\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cp\u003eWindow width: {this.state.width}\u003c/p\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n\nexport default App;\n```\n\nJust like with `useState`, you can use multiple effect in a component:\n\nUsing React Hook\n\n```javascript\nimport React, { useState, useEffect } from 'react';\n\nfunction App() {\n  const [width, setWidth] = useState(window.innerWidth);\n\n  useEffect(() =\u003e {\n    document.title = `Window width: ${width}`;\n  });\n\n  // Similar to componentDidMount and componentDidUpdate:\n  useEffect(() =\u003e {\n    const handleResize = () =\u003e setWidth(window.innerWidth);\n    window.addEventListener('resize', handleResize);\n    // Clean up resize event\n    return () =\u003e {\n      window.removeEventListener('resize', handleResize);\n    };\n  });\n\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003eWindow width: {width}\u003c/p\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default App;\n```\n\nHooks let you organize side effects in a component by what pieces are related (such as adding and removing a event or subscription), rather than forcing a split based on lifecycle methods.\n\n\u003e You can learn more about the Effect Hook on a dedicated page: [Using the Effect Hook](./hooks/using_the_effect_hook.md \"Using the Effect Hook\").\n\n**Building Your Own Hooks**\n\nWell, sometimes we want to reuse some stateful logic between components. Traditionally, there were two popular solutions to this problem: `higher-order components` and `render props`. Custom Hooks let you do this, but without adding more components to your tree.\n\nEarlier on this page, we introduced a App component that calls the `useState` and `useEffect` Hooks to get window width and display on browser title. Let's say we also want to reuse this App logic in another component.\n\nFirst, we'll extract this logic into a custom Hook called `useWindowWidth` and `useDocumentTitle`:\n\n```javascript\nfunction useDocumentTitle(title) {\n  useEffect(() =\u003e {\n    document.title = title;\n  });\n}\n\nfunction useWindowWidth() {\n  const [width, setWidth] = useState(window.innerWidth);\n  useEffect(() =\u003e {\n    const handleResize = () =\u003e setWidth(window.innerWidth);\n    window.addEventListener('resize', handleResize);\n    // Clearn up\n    return () =\u003e {\n      window.removeEventListener('resize', handleResize);\n    };\n  });\n  return width;\n}\n```\n\nNow we can use it from the component:\n\n```javascript\nimport React, { useState, useEffect } from 'react';\n\nfunction App() {\n  const width = useWindowWidth();\n\n  useDocumentTitle(`Window width: ${width}`);\n\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003eWindow width: {width}\u003c/p\u003e\n    \u003c/div\u003e\n  );\n}\n\n\nexport default App;\n```\n\nThe state of these components is completely independent. Hooks are a way to reuse stateful logic, not state itself. In fact, each call to a Hook has a completely isolated state and so you can even use the same custom Hook twice in one component.\n\nTo build your own hooks you need to follow the `useSomething` naming convention. If a function's name starts with \"use\" and it calls other Hooks, we say it is a custom Hook.\n\nYou can write custom Hooks that cover a wide range of use cases like form handling, animation, declarative subscriptions, timers, and probably many more we haven't considered.\n\n\u003e You can learn more about the Building Your Own Hooks on a dedicated page: [Building Your Own Hooks](./hooks/building_your_own_hooks.md \"Building Your Own Hooks\").\n\n**Rules of Hooks**\n\nHooks are JavaScript functions, but they impose two additional rules:\n\n- Only call Hooks at the top level. Don't call Hooks inside loops, conditions, or nested functions.\n- Only call Hooks from React function components. Don't call Hooks from regular JavaScript functions. (There is just one other valid place to call Hooks is your own custom Hooks.)\n\nThe better way you can use a [linter plugin](https://www.npmjs.com/package/eslint-plugin-react-hooks) to enforce these rules automatically.\n\n\u003e You can learn more about the Rules of Hooks on a dedicated page: [Rules of Hooks](./hooks/rules_of_hooks.md \"Rules of Hooks\").\n\n---\n\n## Code-Splitting\n\n### \u003ca name=\"codeSplittingImport\"\u003e\u003c/a\u003e1. import()\n\nThe best way to introduce code-splitting into your app is through the dynamic `import()` syntax.\n\nBefore:\n\n```javascript\nimport { add } from './math';\n\nconsole.log(add(16, 26));\n```\n\nAfter:\n\n```javascript\nimport(\"./math\").then(math =\u003e {\n  console.log(math.add(16, 26));\n});\n```\n\n### \u003ca name=\"codeSplittingLazy\"\u003e\u003c/a\u003e2. lazy\n\nBefore:\n\n```javascript\nimport OtherComponent from './OtherComponent';\n\nfunction MyComponent() {\n  return (\n    \u003cdiv\u003e\n      \u003cOtherComponent /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nAfter:\n\n```javascript\nimport React, {lazy} from 'react';\n\nconst OtherComponent = lazy(() =\u003e import('./OtherComponent'));\n\nfunction MyComponent() {\n  return (\n    \u003cdiv\u003e\n      \u003cOtherComponent /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nThis will automatically load the bundle containing the `OtherComponent` when this component gets rendered.\n\n`lazy` takes a function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component.\n\n### \u003ca name=\"codeSplittingSuspense\"\u003e\u003c/a\u003e3. Suspense\n\nIf the module containing the `OtherComponent` is not yet loaded by the time `MyComponent` renders, we must show some fallback content while we're waiting for it to load - such as a loading indicator. This is done using the `Suspense component`.\n\n```javascript\nimport React, {lazy, Suspense} from 'react';\nconst OtherComponent = lazy(() =\u003e import('./OtherComponent'));\n\nfunction MyComponent() {\n  return (\n    \u003cSuspense fallback={\u003cdiv\u003eLoading...\u003c/div\u003e}\u003e\n      \u003cOtherComponent /\u003e\n    \u003c/Suspense\u003e\n  );\n}\n```\n\n### \u003ca name=\"codeSplittingErrorBoundaries\"\u003e\u003c/a\u003e4. Error boundaries\n\n\u003e Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. \n\u003e\n\u003e Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.\n\nA class component becomes an error boundary once it defines either (or both) of the lifecycle methods `static getDerivedStateFromError()` or `componentDidCatch()`. Use `static getDerivedStateFromError()` to render a fallback UI after an error has been thrown. Use `componentDidCatch()` to log error information.\n\n```javascript\nclass ErrorBoundary extends React.Component {\n  constructor(props) {\n    super(props);\n    this.state = { hasError: false };\n  }\n\n  static getDerivedStateFromError(error) {\n    // Update state so the next render will show the fallback UI.\n    return { hasError: true };\n  }\n\n  componentDidCatch(error, info) {\n    // You can also log the error to an error reporting service\n    // logErrorToMyService(error, info);\n  }\n\n  render() {\n    if (this.state.hasError) {\n      // You can render any custom fallback UI\n      return \u003ch1\u003eSomething went wrong.\u003c/h1\u003e;\n    }\n\n    return this.props.children; \n  }\n}\n```\n\n\u003e Note that error boundaries only catch errors in the components below them in the tree.\n\nOnce you've created your Error Boundary, you can use it anywhere above your lazy components to display an error state when there's a network error.\n\n```javascript\nimport MyErrorBoundary from './MyErrorBoundary';\nconst OtherComponent = React.lazy(() =\u003e import('./OtherComponent'));\nconst AnotherComponent = React.lazy(() =\u003e import('./AnotherComponent'));\n\nconst MyComponent = () =\u003e (\n  \u003cdiv\u003e\n    \u003cMyErrorBoundary\u003e\n      \u003cSuspense fallback={\u003cdiv\u003eLoading...\u003c/div\u003e}\u003e\n        \u003csection\u003e\n          \u003cOtherComponent /\u003e\n          \u003cAnotherComponent /\u003e\n        \u003c/section\u003e\n      \u003c/Suspense\u003e\n    \u003c/MyErrorBoundary\u003e\n  \u003c/div\u003e\n);\n```\n\n### \u003ca name=\"codeSplittingRouteBased\"\u003e\u003c/a\u003e5. Route-based code splitting\n\nDeciding where in your app to introduce code splitting can be a bit tricky.\n\n\u003e A good place to start is with routes.\n\nHere's an example of how to setup route-based code splitting into your app using libraries like [React Router](https://reacttraining.com/react-router \"React Router\") with `lazy`.\n\n```javascript\nimport { BrowserRouter as Router, Route, Switch } from 'react-router-dom';\nimport React, { Suspense, lazy } from 'react';\n\nconst Home = lazy(() =\u003e import('./routes/Home'));\nconst About = lazy(() =\u003e import('./routes/About'));\n\nconst App = () =\u003e (\n  \u003cRouter\u003e\n    \u003cSuspense fallback={\u003cdiv\u003eLoading...\u003c/div\u003e}\u003e\n      \u003cSwitch\u003e\n        \u003cRoute exact path=\"/\" component={Home}/\u003e\n        \u003cRoute path=\"/about\" component={About}/\u003e\n      \u003c/Switch\u003e\n    \u003c/Suspense\u003e\n  \u003c/Router\u003e\n);\n```\n\n### \u003ca name=\"codeSplittingNamedExports\"\u003e\u003c/a\u003e6. Named Exports\n\n\u003e `lazy` currently only supports default exports.\n\n```javascript\n// ManyComponents.js\nexport const MyComponent = /* ... */;\nexport const MyUnusedComponent = /* ... */;\n```\n\nIf the module you want to import uses named exports, you can create an intermediate module that reexports it as the default.\n\n```javascript\n// MyComponent.js\nexport { MyComponent as default } from \"./ManyComponents.js\";\n```\n\nUse like so:\n\n```javascript\n// MyApp.js\nimport React, { lazy } from 'react';\nconst MyComponent = lazy(() =\u003e import(\"./MyComponent.js\"));\n```\n\n---\n\n## Context\n\n\u003e Context provides a way to pass data through the component tree without having to pass props down manually at every level.\n\n- When to Use Context\n- Before You Use Context\n- API\n  - React.createContext\n  - Context.Provider\n  - Class.contextType\n  - Context.Consumer\n- Examples\n  - Dynamic Context\n  - Updating Context from a Nested Component\n  - Consuming Multiple Contexts\n- Caveats\n\n### When to Use Context\n\n\u003e Context is designed to share data that can be considered as \"global\" for a tree of React components, such as the current authenticated user, theme, or preferred language.\n\n\u003e Using context, we can avoid passing props through intermediate elements.\n\n### Before You Use Context\n\n\u003e Context is primarily used when some data needs to be accessible by many components at different nesting levels.\n\n### API\n\nContext API provides a way to pass data through the component tree without having to pass props down manually to every level. In React, data is often passed from a parent to its child component as a property.\n\nUsing the new React Context API depends on three main steps:\n  1. Passing the initial state to `React.createContext`. This function then returns an object with a `Provider` and a `Consumer`.\n  2. Using the `Provider` component at the top of the tree and making it accept a prop called `value`. This value can be anything.\n  3. Using the `Consumer` component anywhere below the Provider in the component tree to get a subset of the state.\n\n#### React.createContext\n\n```javascript\nconst MyContext = React.createContext(defaultValue);\n```\n\n`React.createContext` which is passed the initial value (defaultValue). This returns an object with a Provider and a Consumer.\n\n#### Context.Provider\n\n```javascript\n\u003cMyContext.Provider value={/* some value */}\u003e\n```\n\nThe `Provider` component is used higher in the tree and accepts a prop called value (which can be anything).\n\n#### Class.contextType\n\n- `contextType` is used to:\n  - Perform a side-effect at mount using the value of Context\n  - Render something based on the value of Context\n\n```javascript\nclass MyClass extends React.Component {\n  static contextType = MyContext;\n  componentDidMount() {\n    let value = this.context;\n    /* perform a side-effect at mount using the value of MyContext */\n  }\n  componentDidUpdate() {\n    let value = this.context;\n    /* ... */\n  }\n  componentWillUnmount() {\n    let value = this.context;\n    /* ... */\n  }\n  render() {\n    let value = this.context;\n    /* render something based on the value of MyContext */\n  }\n}\n```\n\n#### Context.Consumer\n\n```javascript\n\u003cMyContext.Consumer\u003e\n  {value =\u003e /* render something based on the context value */}\n\u003c/MyContext.Consumer\u003e\n```\n\nThe `Consumer` component is used anywhere below the provider in the tree and accepts a prop called \"children\" which must be a function that accepts the value and must return a react element (JSX).\n\n#### Examples\n\n##### Dynamic Context\n\n`theme-context.js`\n\n```javascript\nimport React from 'react';\n\nexport const themes = {\n  dark: {\n    foreground: '#ffffff',\n    background: '#222222',\n  },\n  light: {\n    foreground: '#000000',\n    background: '#eeeeee',\n  },\n};\n\nexport const ThemeContext = React.createContext(\n  themes.dark, // default value\n);\n```\n\n`themed-button.js`\n\n```javascript\nimport React from 'react';\n\nimport {ThemeContext} from './theme-context';\n\nclass ThemedButton extends React.Component {\n  render() {\n    let props = this.props;\n    let theme = this.context;\n    \n    return (\n      \u003cbutton\n        {...props}\n        style={{backgroundColor: theme.background}}\n      /\u003e\n    );\n  }\n}\n\nThemedButton.contextType = ThemeContext;\n\nexport default ThemedButton;\n```\n\n`App.js`\n\n```javascript\nimport React, { Component } from 'react';\n\nimport {ThemeContext, themes} from './theme-context';\nimport ThemedButton from './themed-button';\n\n// An intermediate component that uses the ThemedButton\nfunction Toolbar(props) {\n  return (\n    \u003cThemedButton onClick={props.changeTheme}\u003e\n      Change Theme\n    \u003c/ThemedButton\u003e\n  );\n}\n\nclass App extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      theme: themes.light,\n    };\n\n    this.toggleTheme = () =\u003e {\n      this.setState(state =\u003e ({\n        theme:\n          state.theme === themes.dark\n            ? themes.light\n            : themes.dark,\n      }));\n    };\n  }\n\n  render() {\n    // The ThemedButton button inside the ThemeProvider\n    // uses the theme from state while the one outside uses\n    // the default dark theme\n    return (\n      \u003cdiv\u003e\n        \u003cThemeContext.Provider value={this.state.theme}\u003e\n          \u003cToolbar changeTheme={this.toggleTheme} /\u003e\n        \u003c/ThemeContext.Provider\u003e\n        \u003cdiv\u003e\n          \u003cThemedButton /\u003e\n        \u003c/div\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n\nexport default App;\n```\n\n##### Updating Context from a Nested Component\n\nIt is often necessary to update the context from a component that is nested somewhere deeply in the component tree.\n\nIn this case you can pass a function down through the context to allow consumers to update the context:\n\n`theme-context.js`\n\n```javascript\nimport React from 'react';\n\nexport const themes = {\n  dark: {\n    foreground: '#ffffff',\n    background: '#222222',\n  },\n  light: {\n    foreground: '#000000',\n    background: '#eeeeee',\n  },\n};\n\n// Make sure the shape of the default value passed to\n// createContext matches the shape that the consumers expect!\nexport const ThemeContext = React.createContext({\n  theme: themes.dark,\n  toggleTheme: () =\u003e {},\n});\n```\n\n`theme-toggler-button.js`\n\n```javascript\nimport React from 'react';\n\nimport {ThemeContext} from './theme-context';\n\nfunction ThemeTogglerButton() {\n  // The Theme Toggler Button receives not only the theme\n  // but also a toggleTheme function from the context\n  return (\n    \u003cThemeContext.Consumer\u003e\n      {({theme, toggleTheme}) =\u003e (\n        \u003cbutton\n          onClick={toggleTheme}\n          style={{backgroundColor: theme.background}}\u003e\n          Toggle Theme\n        \u003c/button\u003e\n      )}\n    \u003c/ThemeContext.Consumer\u003e\n  );\n}\n\nexport default ThemeTogglerButton;\n```\n\n`App.js`\n\n```javascript\nimport React, { Component } from 'react';\n\nimport {ThemeContext, themes} from './theme-context';\nimport ThemeTogglerButton from './theme-toggler-button';\n\nclass App extends Component {\n  constructor(props) {\n    super(props);\n\n    this.toggleTheme = () =\u003e {\n      this.setState(state =\u003e ({\n        theme:\n          state.theme === themes.dark\n            ? themes.light\n            : themes.dark,\n      }));\n    };\n\n    // State also contains the updater function so it will\n    // be passed down into the context provider\n    this.state = {\n      theme: themes.light,\n      toggleTheme: this.toggleTheme,\n    };\n  }\n\n  render() {\n    // The entire state is passed to the provider\n    return (\n      \u003cThemeContext.Provider value={this.state}\u003e\n        \u003cContent /\u003e\n      \u003c/ThemeContext.Provider\u003e\n    );\n  }\n}\n\nfunction Content() {\n  return (\n    \u003cdiv\u003e\n      \u003cThemeTogglerButton /\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default App;\n```\n\n## \u003ca name=\"reactContextAPIPattern\"\u003e\u003c/a\u003e React Context API Pattern\n\nThe **Context API** is a neat way to pass state across the app without having to use props.\n\nThe Context API was introduced to allow you to pass state (and enable the state to update) across the app, without having to use props for it.\n\nThe React team suggests to stick to props if you have just a few levels of children to pass, because it’s still a much less complicated API than the Context API.\n\nIn many cases, it enables us to avoid using Redux, simplifying our apps a lot, and also learning how to use React.\n\nHow does it work?\n\nYou create a context using `React.createContext()`, which returns a Context object.:\n\n```javascript\nconst { Provider, Consumer } = React.createContext()\n```\n\nThen you create a wrapper component that returns a **Provider** component, and you add as children all the components from which you want to access the context:\n\n```javascript\nclass Container extends React.Component {\n  constructor(props) {\n    super(props)\n    this.state = {\n      something: 'hey'\n    }\n  }\n\n  render() {\n    return (\n      \u003cProvider value={{ state: this.state }}\u003e{this.props.children}\u003c/Provider\u003e\n    )\n  }\n}\n\nclass HelloWorld extends React.Component {\n  render() {\n    return (\n      \u003cContainer\u003e\n        \u003cButton /\u003e\n      \u003c/Container\u003e\n    )\n  }\n}\n```\n\nI used Container as the name of this component because this will be a global provider. You can also create smaller contexts.\n\nInside a component that’s wrapped in a Provider, you use a **Consumer** component to make use of the context:\n\n```javascript\nclass Button extends React.Component {\n  render() {\n    return (\n      \u003cConsumer\u003e\n        {context =\u003e \u003cbutton\u003e{context.state.something}\u003c/button\u003e}\n      \u003c/Consumer\u003e\n    )\n  }\n}\n```\n\nYou can also pass functions into a Provider value, and those functions will be used by the Consumer to update the context state:\n\n```javascript\n\u003cProvider value={{\n  state: this.state,\n  updateSomething: () =\u003e this.setState({something: 'ho!'})\n  {this.props.children}\n\u003c/Provider\u003e\n\n/* ... */\n\u003cConsumer\u003e\n  {(context) =\u003e (\n    \u003cbutton onClick={context.updateSomething}\u003e{context.state.something}\u003c/button\u003e\n  )}\n\u003c/Consumer\u003e\n```\n\nYou can create multiple contexts, to make your state distributed across components, yet expose it and make it reachable by any component you want.\n\nWhen using multiple files, you create the content in one file, and import it in all the places you use it:\n\n```javascript\n//context.js\nimport React from 'react'\nexport default React.createContext()\n\n//component1.js\nimport Context from './context'\n//... use Context.Provider\n\n//component2.js\nimport Context from './context'\n//... use Context.Consumer\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbunlong%2Freact-in-practice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbunlong%2Freact-in-practice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbunlong%2Freact-in-practice/lists"}