{"id":21890774,"url":"https://github.com/chantastic/reactcontext.com","last_synced_at":"2025-06-20T07:35:57.419Z","repository":{"id":42247508,"uuid":"126871647","full_name":"chantastic/reactcontext.com","owner":"chantastic","description":"a gentle intro to the what, where, when, why, and how of React Context","archived":false,"fork":false,"pushed_at":"2025-01-21T20:17:16.000Z","size":248,"stargazers_count":9,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-28T20:36:40.212Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://reactcontext.com","language":"Astro","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/chantastic.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}},"created_at":"2018-03-26T18:22:46.000Z","updated_at":"2024-12-16T22:21:10.000Z","dependencies_parsed_at":"2022-08-20T20:31:49.744Z","dependency_job_id":null,"html_url":"https://github.com/chantastic/reactcontext.com","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chantastic%2Freactcontext.com","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chantastic%2Freactcontext.com/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chantastic%2Freactcontext.com/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chantastic%2Freactcontext.com/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chantastic","download_url":"https://codeload.github.com/chantastic/reactcontext.com/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249081516,"owners_count":21209712,"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":[],"created_at":"2024-11-28T12:16:48.529Z","updated_at":"2025-04-15T13:39:04.987Z","avatar_url":"https://github.com/chantastic.png","language":"Astro","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Context\n\n*Updated for React 19.*\n\n## TLDR on React Context\n\nUse Context for *implicit*, client-only, data distribution.  \nContext is an alternative props (which are *explicit* and available to both server and client components).\n\nContext allows for component relationships similar to HTML elements `\u003cli\u003e` and `\u003col\u003e`.  \nHere, data applied to the parent, has an implicit impact on how children render.\n\n```jsx title=\"an HTML comparison\"\n\u003col start=\"10\"\u003e\n  \u003cli\u003eTenth\u003c/li\u003e\n  \u003cli\u003eEleventh\u003c/li\u003e\n  \u003cli\u003eTwelfth\u003c/li\u003e\n\u003c/ol\u003e\n```\n\nContext makes a value available to all descendents.\n\n```jsx title=\"parent providing context\"\n\u003cUserContext value={user}\u003e\n  \u003cUserAvatar /\u003e\n  \u003cUserName /\u003e\n\u003c/UserContext\u003e\n```\n\nThose descendents must opt in to Context.\n\n```jsx title=\"child component using context\"\nfunction UserAvatar() {\n  let user = React.use(UserContext);\n\n  return \u003cimg src={user.avatar_url} /\u003e;\n}\n```\n\nUnlike HTML, Context does not require direct parent-child relationships.  \nContexts can be sent and recieved *\"thru\"* intermediate elements, components, and context providers.\n\n```jsx title=\"child composing two contexts\"\n\u003cOrgContext value=\"ACME Co.\"\u003e\n  \u003cPersonContext value=\"Yakko\"\u003e\n    \u003cdiv class=\"my-layout\"\u003e\n      \u003cOrganizationBizCard /\u003e\u003c!-- Yakko, ACME Co. --\u003e\n    \u003c/div\u003e\n  \u003c/PersonContext\u003e\n\u003c/OrgContext\u003e\n```\n\nThis doc is a guide for implementing Context in React.\n\n\u003c!-- Begin MailChimp Signup Form --\u003e\n\u003cdiv id=\"mc_embed_signup\" style=\"padding-top: 1em\"\u003e\n\u003cform action=\"https://learnreact.us9.list-manage.com/subscribe/post?u=03b6ee2f58c8b4427c8ba9735\u0026amp;id=f97aebbc64\" method=\"post\" id=\"mc-embedded-subscribe-form\" name=\"mc-embedded-subscribe-form\" class=\"validate\" target=\"_blank\" novalidate\u003e\n    \u003cdiv id=\"mc_embed_signup_scroll\"\u003e\n\t\u003cinput type=\"email\" value=\"\" name=\"EMAIL\" class=\"email\" id=\"mce-EMAIL\" placeholder=\"email address\" required\u003e\n    \u003c!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--\u003e\n    \u003cdiv style=\"position: absolute; left: -5000px;\" aria-hidden=\"true\"\u003e\u003cinput type=\"text\" name=\"b_03b6ee2f58c8b4427c8ba9735_f97aebbc64\" tabindex=\"-1\" value=\"\"\u003e\u003c/div\u003e\n    \u003cdiv class=\"clear\"\u003e\u003cinput type=\"submit\" value=\"Subscribe\" name=\"subscribe\" id=\"mc-embedded-subscribe\" class=\"button\"\u003e\u003c/div\u003e\n    \u003c/div\u003e\n\u003c/form\u003e\n\u003c/div\u003e\n\u003c!--End mc_embed_signup--\u003e\n\n## Table of contents\n\n## Real-world React Context (a \"shit\" example)\n\n*Shit* is fine word in my house. But my mom hates it.\nSo I tell my kids to use another word when around grandma.  \n\nHere's how I'd implement that with React Context.\n\n```jsx\n// It's ok to say \"shit\" as a default expletive\nlet ExpletiveContext = React.createContext(\"shit\");\n\n// But context is important. Learn to account for it.\nfunction ContextualExclamation() {\n  let word = React.use(ExpletiveContext);\n\n  return \u003cspan\u003eOh {word}!\u003c/span\u003e;\n}\n\n// When at Grandma's house, say \"snap\" instead\nfunction AtGrandmasHouse() {\n  return (\n    \u003cExpletiveContext value=\"snap\"\u003e\n      \u003cContextualExclamation /\u003e\n    \u003c/ExpletiveContext\u003e\n  )\n);\n\n// =\u003e \u003cspan\u003eOh snap!\u003c/span\u003e\n```\n\n## Context is a 3-part system: create, use, and provide\n\nContext is a 3-part system:\n**create**, **use**, **provide**.\n\n**Create** context with `React.createContext`.\n\n```jsx title=\"create context\"\nlet NameContext = React.createContext(\"Guest\");\n```\n\n**Use** context with `React.use`.\n\n```jsx title=\"use context\"\nfunction ContextualGreeting() {\n  let name = React.use(NameContext);\n\n  return \u003ch1\u003e👋 {name}!\u003c/h1\u003e;\n}\n```\n\n**Provide** context by rendering the `Context` with a `value` prop.  \n\n```jsx title=\"provide context value\"\n\u003cNameContext value=\"Chan\"\u003e\n  \u003cContextualGreeting /\u003e\n\u003c/NameContext\u003e\n\n// =\u003e \u003ch1\u003e👋 Chan!\u003c/h1\u003e\n```\n\n## Context is an alternative to props that is implicit\n\nContext is most useful when many components require the same data.\n\nHere's an example:\n\n```jsx title=\"app.jsx\"\n\u003c\u003e\n  \u003cUserAvatar user={user} /\u003e\n  \u003cUserTimeline user={user} /\u003e\n  \u003cUserRelatedPosts user={user} /\u003e\n\u003c/\u003e\n```\n\nThese components may, in turn, also pass the same data to their children.\n\n```jsx title=\"user_avatar.jsx\" {9}\nfunction UserRelatedPosts({ user }) {\n  const related_posts = getRelatedPosts(user);\n\n  return (\n    \u003cul\u003e\n      {related_posts.map(post =\u003e (\n        \u003cli\u003e\n          \u003cspan\u003e{post.body}\u003c/span\u003e\n          \u003cUserMiniProfile user={user} /\u003e\n        \u003c/li\u003e\n      ))}\n    \u003c/ul\u003e\n  );\n}\n```\n\nWith Context, the data is set once on the parent.\n\n```jsx title=\"app.jsx\" ins=/(UserContext.*)\u003e/ del=/ user={user}/\n\u003cUserContext value={user}\u003e\n  \u003cUserAvatar user={user} /\u003e\n  \u003cUserTimeline user={user} /\u003e\n  \u003cUserRelatedPosts user={user} /\u003e\n\u003c/UserContext\u003e\n```\n\nAnd descendent components opt into this data with `use`.\n\n```jsx title=\"user_avatar.jsx\" ins=/const user =.+/ del=/{ user }/\nfunction UserAvatar({ user }) {\n  const user = React.use(UserContext);\n\n  return \u003cimg src={user.avatar_url} /\u003e;\n}\n```\n\n## Think of props like wired and Context like wireless (a mental model)\n\n**Props are like wires.**  \nThey \"connect\" data between components.  \nLike wires, the components have to be \"touching\".  \nMeaning that components *holding* data have to render components that *need* it.\n\n**Context is like a wireless.**  \nIt sends a \"signal\" that is received by children.  \nLike wireless, components don't need to be \"touching\" they only need to be \"in range\".\nMeaning that children of context can *recieve* the signal that context sends.\n\n## Context is available to all descendents (indifferent to how deeply nested)\n\nEvery descendent/child of a Context provider can observe Context's value.\n\n```jsx title=\"any descendent can recieve context\" {4, 7, 10}\nfunction App() {\n  return (\n    \u003cUserContext value={user}\u003e\n      {/* UserContext can be received here… */}\n\n      \u003cdiv className=\"app-layout\"\u003e\n        {/* also here… */}\n\n        \u003cdiv className=\"page-layout\"\u003e\n          {/* and anywhere in this tree… */}\n        \u003c/div\u003e\n      \u003c/div\u003e\n    \u003c/UserContext\u003e\n  );\n}\n```\n\n## Context is composable\n\nContexts can be chidren of other Contexts. Order doesn't matter much unless it matters to your app.\n\n```jsx title=\"two contexts; one component\"\nlet OrgContext = React.createContext();\nlet PersonContext = React.createContext();\n\nfunction App() {\n  return (\n    \u003cOrgContext value=\"ACME Co.\"\u003e\n      \u003cPersonContext value=\"Yakko\"\u003e\n        \u003cUserOrgBizCard /\u003e\u003c!-- Yakko, ACME Co. --\u003e\n      \u003c/PersonContext\u003e\n    \u003c/OrgContext\u003e\n  );\n}\n\nfunction UserOrgBizCard() {\n  const org_name = React.use(OrgContext);\n  const person_name = React.use(PersonContext);\n\n  return (\n    \u003cdiv className=\"business-card\"\u003e\n      {person_name}, {org_name}\n    \u003c/div\u003e\n  );\n}\n```\n\n## Context can not be sent \"over the wire\" (it's not available to the server)\n\nContext is only available to client components.  \nServer components cannot recieve context.\n\n## Context is used to implement the compound components pattern\n\nThe \"compound component\" pattern describes components that are isolated but interdependent.\nIn HTML, `li` and `ol` are interdepedent. As are `option` and `select`.\n\nThis same interdependent relationship can be implemented using React Context.\n\n```jsx title=\"app.jsx\"\nimport * as React from \"react\";\nimport * as User from \"./user\";\n\nfunction App() {\n  const [editing, setEditing] = React.useState(false);\n\n  const [user, setUser] = React.useState({\n    name: \"Guest\",\n    avatar_url: \"https://example.com/avatar.png\"\n  });\n\n  return (\n    \u003cUser.Context value={user}\u003e\n      {isEditing\n        ? \u003cUser.Form\n            action={formData =\u003e {\n              setUser({ name: formData.get('name') });\n              setEditing(false);\n            }}\n          /\u003e\n        : \u003c\u003e\n            \u003cUser.Avatar /\u003e\n            \u003cUser.Name /\u003e\n            \u003cbutton onClick={() =\u003e setEditing(true)}\u003e\n              Edit\n            \u003c/button\u003e\n          \u003c/\u003e\n      }\n    \u003c/User.Context\u003e\n  );\n}\n```\n\n\u003cdiv style=\"margin-bottom: 2rem\"\u003e\u003c/div\u003e\n\n```jsx title=\"user.jsx\"\nimport * as React from \"react\";\n\nexport const Context = React.createContext();\n\nfunction Avatar() {\n  const user = React.use(UserContext);\n\n  return \u003cimg className=\"user-avatar\" src={user.avatar_url} /\u003e\n}\n\nfunction Name() {\n  const user = React.use(UserContext);\n\n  return (\n    \u003cspan className=\"user-name\"\u003e{user.name}\u003c/span\u003e\n  );\n}\n\nfunction Form({ action }) {\n  const user = React.use(UserContext);\n\n  return (\n    \u003cform\n      className=\"user-form\"\n      action={action}\n    \u003e\n      \u003cinput type=\"text\" name=\"name\" defaultValue={user.name} /\u003e\n    \u003c/form\u003e\n  );\n}\n```\n\n## Context can be used to implement distributed state management (with useReducer)\n\nContext makes it possible to distribute data to every component in a component tree.\n\nIt's used to distribute data, not manage state.\nThat said, it provides the mechanism needed to both distribute state and dispatch updates.\n\nHere's an minimum connection of the two.\n\n```jsx title=\"app.jsx\"\nimport * as React from 'react';\nimport * as ClickCount from './click_count';\n\nfunction App() {\n  const clickState = React.useReducer(\n    ClickCount.reducer,\n    ClickCount.initialState\n  );\n\n  return (\n    \u003cClickCount.Context value={clickState}\u003e\n      \u003cstrong\u003e\n        \u003cClickCount.Show /\u003e\n      \u003c/strong\u003e\n      \u003cbr /\u003e\n      \u003cClickCount.IncrementAction /\u003e\n    \u003c/ClickCount.Context\u003e\n  );\n}\n```\n\n```jsx title=\"click_count.jsx\"\nimport * as React from 'react';\n\nexport const initialState = { count: 0 };\n\nexport function reducer(state, action) {\n  switch (action.type) {\n    case 'increment':\n      return { count: state.count + 1 };\n    default:\n      return state;\n  }\n}\n\nexport const Context = React.createContext();\n\nexport function Show() {\n  let [state] = React.use(Context);\n\n  return \u003c\u003e{state.count}\u003c/\u003e;\n}\n\nexport function IncrementAction() {\n  let [, dispatch] = React.use(Context);\n\n  return (\n    \u003cbutton onClick={() =\u003e dispatch({ type: 'increment' })}\u003e\n      Increment count\n    \u003c/button\u003e\n  );\n}\n```\n\n## Any JavaScript value can be be shared via Context\n\nContext can take any shape.  \nHere are examples of valid Contexts values, using a default `value`:\n\n```jsx\nlet StringContext = React.createContext(\"string\");\n\nlet NumberContext = React.createContext(42);\n\nlet FunctionContext = React.createContext(() =\u003e\n  alert(\"Context function\")\n);\n\nlet ArrayContext = React.createContext([\n  \"some\",\n  \"array\",\n  \"elements\"\n]);\n\nlet ObjectContext = React.createContext({\n  aString: \"string\",\n  aNumber: 42,\n  aFunction: () =\u003e alert(\"Context function\"),\n  anArray: [\"some\", \"array\", \"elements\"]\n});\n\nlet MapAndSetContext = React.createContext(\n  new Map([\n    [\n      'Taylor Swift',\n      new Set(['Tortured Poets Department', 'Midnights', 'Evermore']),\n    ],\n  ])\n);\n```\n\n`value` can be complex structures like React Elements, class components, and function components.\n\n```jsx\nlet ReactElementContext = React.createContext(\n  \u003cspan\u003eReact Element\u003c/span\u003e\n);\n\nlet FunctionalComponentContext = React.createContext(\n  props =\u003e \u003cspan\u003eFunction Component\u003c/span\u003e\n);\n```\n\n## You can set a default `value` when creating Context\n\nContext can be initialized with a default `value`.\nWhen a component attempts to `use` Context, but no corresponding `Context` is found, a default value will be used.\n\n```jsx\nlet UserContext = React.createContext(\"Guest\");\n\nfunction UserGreeting () {\n  let name = React.use(UserContext);\n\n  return \u003cspan\u003eHi {name}!\u003c/span\u003e;\n}\n\nlet App = props =\u003e (\n  \u003cdiv\u003e\n    \u003cContextGreeting /\u003e\n    {/* =\u003e Hi Guest! */}\n\n    \u003cUserContext value=\"Bulbasaur\"\u003e\n      \u003cContextGreeting /\u003e\n      {/* =\u003e Hi Bulbasaur! */}\n    \u003c/UserContext\u003e\n  \u003c/div\u003e\n);\n```\n\n## Context can be used inline with the render prop pattern\n\nContext exposes a `Consumer` component for inline context use. This allows context to be consumed without creating new components.\n\n```jsx\n\u003cSomeContext value=\"some value\"\u003e\n  \u003cSomeContext.Consumer\u003e\n    {value =\u003e \u003cspan\u003e{value}\u003c/span\u003e}\n  \u003c/SomeContext.Consumer\u003e\n\u003c/SomeContext\u003e\n```\n\n\nHere's an example where multiple contexts are created and used.\n\n```jsx\nconst OrgContext = React.createContext();\nconst PersonContext = React.createContext();\n\nfunction App () {\n  return (\n    \u003cOrgContext value=\"ACME Co.\"\u003e\n      \u003cPersonContext value=\"Yakko\"\u003e\n        \u003cOrgContext.Consumer\u003e\n          {organization =\u003e (\n            \u003cPersonContext.Consumer\u003e\n              {person =\u003e (\n                \u003cspan\u003e\n                  {person}, {organization}\n                \u003c/span\u003e\n              )}\n            \u003c/PersonContext.Consumer\u003e\n          )}\n        \u003c/Organization.Consumer\u003e\n      \u003c/PersonContext\u003e\n    \u003c/OrgContext\u003e\n  )\n}\n\n// =\u003e Yakko, ACME Co.\n```\n\n## Context can cascade\n\nConsumers use the value from the nearest `Context`.  \nWhere none is present, the `createContext` default value is used.\n\n```jsx\nconst MyContext = React.createContext(\"default\");\n\nfunction ShowContextValue() {\n  const value = React.use(MyContext);\n\n  return \u003c\u003e{value}\u003c/\u003e;\n}\n\nfunction App() {\n  return (\n    \u003c\u003e\n      \u003cMyContext value=\"outer\"\u003e\n        \u003cShowContext /\u003e {/* \"outer\" */}\n\n        \u003cMyContext value=\"inner\"\u003e\n          \u003cShowContext /\u003e {/* \"inner\" */}\n        \u003c/MyContext\u003e\n      \u003c/Provider\u003e\n\n      \u003cShowContext /\u003e {/* \"default\" */}\n    \u003c/\u003e\n  );\n}\n```\n\n## What is Legacy Context?\n\nLegacy Context refers to a set of APIs that were removed in React 19.  \nThese include class-based component context.\n\nRead the [Legacy Context doc](https://reactjs.org/docs/legacy-context.html) for more details.\n\n\u003cdiv style=\"margin-bottom: 8rem\"\u003e\u003c/div\u003e\n\n\u0026copy; 2024 Michael Chan, Some Rights Reserved\n\n\u003ca rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\"\u003e\u003cimg alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png\" /\u003e\u003c/a\u003e\u003cbr /\u003eThis work is licensed under a \u003ca rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\"\u003eCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License\u003c/a\u003e.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchantastic%2Freactcontext.com","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchantastic%2Freactcontext.com","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchantastic%2Freactcontext.com/lists"}