mirror of
https://github.com/Dvorinka/Devour.git
synced 2026-06-03 20:13:03 +00:00
17 lines
10 KiB
JSON
17 lines
10 KiB
JSON
{
|
|
"id": "a1106259a76b0a6721eca654",
|
|
"source": "solid:signals",
|
|
"type": "github-document",
|
|
"title": "context",
|
|
"content": "---\ntitle: Context\norder: 5\nuse_cases: \u003e-\n global state management, avoiding prop drilling, theme providers,\n authentication state, shared data across components\ntags:\n - context\n - state\n - global\n - providers\n - sharing\n - management\nversion: '1.0'\ndescription: \u003e-\n Share data across component trees with Solid's Context API. Avoid prop\n drilling and manage global application state effectively.\n---\n\nContext 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\nWhen you have a large [component tree](/concepts/components/basics#component-trees) that requires state to be shared, context can be used.\nContext can be employed to avoid [prop drilling](/concepts/components/props#prop-drilling), which is the practice of passing props through intermediate elements without using them directly.\n\nIf you want to avoid passing some props through a few layers, when applicable, adjusting your component hierarchy may be an easier solution.\n[Signals](/concepts/signals) are often the simplest solution since they can be imported directly into the components that need them.\n\nContext, however, is designed to share data that is global to an application or for information that is regularly accessed by multiple components in an application's component tree.\nThis offers a way to access state across an application without passing props through intermediate layers or importing them directly into components.\n\n## Creating context\n\nContext is created using the [`createContext`](/reference/component-apis/create-context) function.\nThis function has a `Provider` property that wraps the component tree you want to provide context to.\n\n```jsx tab title=\"/context/create.js\"\nimport { createContext } from \"solid-js\";\n\nexport const MyContext = createContext();\n```\n\n```jsx tab title=\"/context/component.jsx\"\nimport { MyContext } from \"./create\";\n\nexport function Provider (props) {\n\treturn (\n\t\t\u003cMyContext.Provider\u003e\n\t\t\t{props.children}\n\t\t\u003c/MyContext.Provider\u003e\n\t)\n};\n```\n\n## Providing context to children\n\nTo pass a value to the `Provider`, you use the `value` prop which can take in any value, including [signals](#updating-context-values).\nOnce a value is passed to the `Provider`, it is available to all components that are descendants of the `Provider`.\n\nWhen passing a single value, it can be directly passed to the `value` prop:\n\n```jsx title=\"/context/component.jsx\"\nimport { createContext, useContext } from \"solid-js\";\nimport { MyContext } from \"./create\";\n\nconst Provider = (props) =\u003e (\n\t\u003cMyContext.Provider value=\"new value\"\u003e{props.children}\u003c/MyContext.Provider\u003e\n);\n```\n\n:::tip[Complex Types]\nWhen passing multiple values (as an `array` or `object`), it is recommended to use a [store](/reference/component-apis/create-context#usage).\n:::\n\n## Consuming context\n\nOnce the values are available to all the components in the context's component tree, they can be accessed using the [`useContext`](/reference/component-apis/use-context) utility.\nThis utility takes in the context object and returns the value(s) passed to the `Provider`:\n\n```jsx title=\"/context/component.jsx\"\nimport { createContext, useContext } from \"solid-js\";\nimport { MyContext } from \"./create\";\n\nconst Provider = (props) =\u003e (\n\t\u003cMyContext.Provider value=\"new value\"\u003e\n\t\t{props.children}\n\t\u003c/MyContext.Provider\u003e\n);\n\nconst Child = () =\u003e {\n\tconst value = useContext(MyContext);\n\n\treturn (\n\t\t\u003cspan\u003e\n\t\t\t{value}\n\t\t\u003c/span\u003e\n\t);\n};\n\nexport const App = () =\u003e (\n\t\u003cProvider\u003e\n\t\t\u003cChild /\u003e\n\t\u003c/Provider\u003e\n);\n```\n\n## Customizing Context Utilities\n\nWhen an application contains multiple context objects, it can be difficult to keep track of which context object is being used.\nTo solve this issue, you can create a custom utility to create a more readable way to access the context values.\n\nFor example, when wrapping a component tree, you may want to create a custom `Provider` component that can be used to wrap the component tree.\nThis also provides you with the option of re-using the `Provider` component in other parts of your application, if needed.\n\n```jsx\nimport { createSignal, createContext, useContext } from \"solid-js\";\nimport { CounterContext } from \"~/context/counter\";\n\nexport function CounterProvider(props) {\n\treturn (\n\t\t\u003cCounterContext.Provider value={props.count ?? 0}\u003e\n\t\t\t{props.children}\n\t\t\u003c/CounterContext.Provider\u003e\n\t);\n}\n```\n\nNow if you had to access the Provider in different areas of your application, you can simply import the `CounterProvider` component and wrap the component tree:\n\n```jsx\nimport { CounterProvider } from \"./counterProvider\";\n\nexport function App() {\n\treturn (\n\t\t\u003cCounterProvider count={1}\u003e\n\t\t\t\u003ch1\u003eWelcome to Counter\u003c/h1\u003e\n\t\t\t\u003cNestedComponents /\u003e\n\t\t\u003c/CounterProvider\u003e\n\t);\n}\n```\n\nSimilarly, you can create a custom utility to access the context values.\nInstead of importing `useContext` and passing in the context object on each component that you're using it in, creating a customized utility can make it easier to access the values you need:\n\n```jsx\nexport function useCounter() {\n\treturn useContext(CounterContext);\n}\n```\n\nThe `useCounter()` utility in this example can now be imported into any component that needs to access the context values:\n\n```jsx\nimport { useCounter } from \"./counter\";\n\nexport function CounterProvider(props) {\n\tconst count = useCounter();\n\treturn (\n\t\t\u003c\u003e\n\t\t\t\u003cdiv\u003e{count()}\u003c/div\u003e\n\t\t\u003c/\u003e\n\t);\n}\n```\n\n## Updating Context Values\n\n[Signals](/concepts/signals) offer a way to synchronize and manage data shared across your components using context.\nYou can pass a signal directly to the `value` prop of the `Provider` component, and any changes to the signal will be reflected in all components that consume the context.\n\n```jsx tab title=\"App.jsx\"\nimport { CounterProvider } from \"./Context\";\nimport { Child } from \"./Child\";\n\nexport function App() {\n\treturn (\n\t\t\u003cCounterProvider count={1}\u003e\n\t\t\t\u003ch1\u003eWelcome to Counter App\u003c/h1\u003e\n\t\t\t\u003cChild /\u003e\n\t\t\u003c/CounterProvider\u003e\n\t)\n}\n```\n\n```jsx tab title=\"Context.jsx\"\nimport { createSignal, useContext } from \"solid-js\";\n\nexport function CounterProvider(props) {\n\tconst [count, setCount] = createSignal(props.initialCount || 0);\n\tconst counter = [\n\t\tcount,\n\t\t{\n\t\t\tincrement() {\n\t\t\tsetCount(prev =\u003e prev + 1);\n\t\t\t},\n\t\t\tdecrement() {\n\t\t\tsetCount(prev =\u003e prev - 1);\n\t\t\t}\n\t\t}\n\t];\n\n\treturn (\n\t\t\u003cCounterContext.Provider value={counter}\u003e\n\t\t\t{props.children}\n\t\t\u003c/CounterContext.Provider\u003e\n\t);\n}\n\nexport function useCounter() { return useContext(CounterContext); }\n```\n\n```tsx tab title=\"Child.jsx\"\n// /context/counter-component.tsx\nimport { useCounter } from \"./Context\";\n\nexport function Child(props) {\n\tconst [count, { increment, decrement }] = useCounter();\n\n\treturn (\n\t\u003c\u003e\n\t\t\u003cdiv\u003e{count()}\u003c/div\u003e\n\t\t\u003cbutton onClick={increment}\u003e+\u003c/button\u003e\n\t\t\u003cbutton onClick={decrement}\u003e-\u003c/button\u003e\n\t\u003c/\u003e\n\t);\n};\n```\n\nThis offers a way to manage state across your components without having to pass props through intermediate elements.\n\n## Debugging with context\n\n`createContext` takes in an _optional_ default value and it is possible it can return `undefined` if not provided.\nWhen working with TypeScript, this can introduce type issues that make it difficult to determine why your component is not rendering as expected.\n\nTo solve this issue, a default value can be specified when creating a context object, or errors can be handled manually through the use of a custom `useMyContext` utility:\n\n```tsx title=\"/context/counter-component.tsx\"\nimport { useContext } from \"solid-js\";\n\nfunction useMyContext() {\n const value = useContext(MyContext);\n\n if (!value) {\n throw new Error(\"Missing context Provider\");\n }\n\n return value;\n}\n\nfunction Child() {\n const value = useMyContext();\n\n return \u003cdiv\u003e{value}\u003c/div\u003e;\n}\n```\n\n## Common issues with `createContext` and `useContext`\n\nIf no default value is passed to `createContext`, it is possible for `useContext` to return `undefined`.\n\n:::note[More on default values]\nRead more about default values in the [`createContext`](/reference/component-apis/create-context) entry.\n:::\n\nBecause of this, if an initial value was not passed to `createContext`, the TS type signature of `useContext` will indicate that\nthe value returned might be `undefined` (as mentioned above).\nThis can be quite annoying when you want to use the context inside a component, and particularly when immediately destructuring the context.\nAdditionally, if you use `useContext` and it returns `undefined` (which is often, but not always, the result of a bug), the error message thrown at runtime can be confusing.\n\nThe most common solution for it is to wrap all uses of `useContext` in a function that will explicitly throw a helpful error if the context is `undefined`.\nThis also serves to narrow the type returned, so TS doesn't complain.\nAs an example:\n\n```ts title=\"/context/counter-component.tsx\"\nfunction useCounterContext() {\n\tconst context = useContext(CounterContext)\n\tif (!context) {\n\t\tthrow new Error(\"can't find CounterContext\")\n\t}\n\treturn context\n}\n```",
|
|
"url": "https://github.com/solidjs/solid-docs/blob/HEAD/src/routes/concepts/context.mdx",
|
|
"metadata": {
|
|
"path": "src/routes/concepts/context.mdx",
|
|
"repo": "solidjs/solid-docs",
|
|
"repo_url": "https://github.com/solidjs/solid-docs.git",
|
|
"size": 8997,
|
|
"source_type": "github"
|
|
},
|
|
"hash": "424dfe9993e3a8597c90ccf0c220cf761aeb1ca564d6df36032990e13a7a4b49",
|
|
"timestamp": "2026-02-23T11:43:00.186467504+01:00"
|
|
} |