Skip to content

Commit ce9e9b6

Browse files
committed
Merged useFn and context
1 parent 55916fb commit ce9e9b6

File tree

4 files changed

+76
-68
lines changed

4 files changed

+76
-68
lines changed

packages/context/README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ Note that this component solely serves as syntactic sugar and doesn't provide an
141141

142142
### How to use it
143143

144-
`ConsumeContext` takes a `useFn` prop with the context's `use...()` function and a `children` prop that will receive the context value. The use function may directly come from `createContextProvider()`.
144+
`ConsumeContext` takes a `use` prop that can be either one of the following:
145+
* A `use...()` function returned by `createContextProvider` or a inline function that returns the context value like `() => useContext(MyContext)`.
146+
* A `context` prop that takes a raw SolidJS context created by `createContext()`.
145147

146148
```tsx
147149
import { createContextProvider, ConsumeContext } from "@solid-primitives/context";
@@ -155,27 +157,27 @@ const [CounterProvider, useCounter] = createContextProvider(() => {
155157

156158
// Provide it, consume it and use it in the same JSX block
157159
<CounterProvider>
158-
<ConsumeContext useFn={useCounter}>
160+
<ConsumeContext use={useCounter}>
159161
{({ count, increment }) => (
160162
<div>
161163
<button onClick={increment}>Increment</button>
162164
<span>{count()}</span>
163165
</div>
164166
)}
165167
</ConsumeContext>
166-
</CounterProvider>;
168+
</CounterProvider>
167169
```
168170

169-
Alternatively, you may also pass the raw SolidJS context over `context` in case you have created a context using `createContext()`.
171+
With the raw SolidJS context returned by `createContext()`:
170172

171173
```tsx
172174
import { ConsumeContext } from "@solid-primitives/context";
173175

174176
// Create a context
175-
const CounterContext = createContext(/*...*/);
177+
const counterContext = createContext(/*...*/);
176178

177179
// Consume it using the raw context
178-
<ConsumeContext context={CounterContext}>
180+
<ConsumeContext use={counterContext}>
179181
{({ count, increment }) => {
180182
// ...
181183
}}

packages/context/src/index.ts

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -135,31 +135,49 @@ export function MultiProvider<T extends readonly [unknown?, ...unknown[]]>(props
135135
* </CounterProvider>
136136
* ```
137137
*
138-
* @param useFn A function that returns the context value. Preferably the `use...()` function returned from `createContextProvider()`.
139-
* @param context The context object itself returned by `createContext()`. If `useFn` is provided, this will be ignored.
138+
* @param use Either one of the following:
139+
* - A function that returns the context value. Preferably the `use...()` function returned from `createContextProvider()`.
140+
* - The context itself returned from `createContext()`.
141+
* - A inline function that returns the context value.
140142
*
141143
* @example
142144
* ```tsx
143145
* // create the context
144146
* const [CounterProvider, useCounter] // = createContextProvider(...)
145147
*
146-
* // use the context
147-
* <ConsumeContext useFn={useCounter}>
148-
* {({ count }) => (
149-
* <div>Count: {count()}</div>
150-
* )}
151-
* </ConsumeContext>
148+
* // provide and use the context
149+
* <CounterProvider count={1}>
150+
* <ConsumeContext use={useCounter}>
151+
* {({ count }) => (
152+
* <div>Count: {count()}</div>
153+
* )}
154+
* </ConsumeContext>
155+
* </CounterProvider>
156+
* ```
157+
*
158+
* ```tsx
159+
* // create the context
160+
* const counterContext = createContext({ count: 0 });
161+
*
162+
* // provide and use the context
163+
* <counterContext.Provider value={{ count: 1 }}>
164+
* <ConsumeContext use={counterContext}>
165+
* {({ count }) => (
166+
* <div>Count: {count}</div>
167+
* )}
168+
* </ConsumeContext>
169+
* </counterContext.Provider>
152170
* ```
153171
*/
154172
export function ConsumeContext<T>(props: {
155-
children: (value: T | undefined) => JSX.Element
156-
} & ({
157-
useFn: () => T | undefined,
158-
context?: never;
159-
} | {
160-
useFn?: never;
161-
context: Context<T>;
162-
})): JSX.Element {
163-
const context = props.useFn ? props.useFn() : useContext(props.context);
173+
children: (value: T | undefined) => JSX.Element,
174+
use: (() => T | undefined) | Context<T>,
175+
}): JSX.Element {
176+
let context: T | undefined;
177+
if (typeof props.use === "function") {
178+
context = props.use();
179+
} else {
180+
context = useContext(props.use);
181+
}
164182
return props.children(context);
165183
}

packages/context/test/index.test.tsx

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -109,41 +109,35 @@ describe("MultiProvider", () => {
109109
});
110110

111111
describe("ConsumeContext", () => {
112-
test("consumes a context via use-function", () => {
112+
test("consumes a context", () => {
113113
const Ctx = createContext<string>("Hello");
114+
const useCtx = () => useContext(Ctx);
114115

115-
function useCtx() {
116-
return useContext(Ctx);
117-
}
118-
119-
let capture;
116+
let capture1;
117+
let capture2;
118+
let capture3;
120119
createRoot(() => {
121120
<Ctx.Provider value="World">
122-
<ConsumeContext useFn={useCtx}>
121+
<ConsumeContext use={Ctx}>
123122
{value => (
124-
capture = value
123+
capture1 = value
125124
)}
126125
</ConsumeContext>
127-
</Ctx.Provider>;
128-
});
129-
130-
expect(capture).toBe("World");
131-
});
132-
133-
test("consumes a context via context object", () => {
134-
const Ctx = createContext<string>("Hello");
135-
136-
let capture;
137-
createRoot(() => {
138-
<Ctx.Provider value="World">
139-
<ConsumeContext context={Ctx}>
126+
<ConsumeContext use={useCtx}>
140127
{value => (
141-
capture = value
128+
capture2 = value
129+
)}
130+
</ConsumeContext>
131+
<ConsumeContext use={() => useContext(Ctx)}>
132+
{value => (
133+
capture3 = value
142134
)}
143135
</ConsumeContext>
144136
</Ctx.Provider>;
145137
});
146138

147-
expect(capture).toBe("World");
139+
expect(capture1).toBe("World");
140+
expect(capture2).toBe("World");
141+
expect(capture3).toBe("World");
148142
});
149143
});

packages/context/test/server.test.tsx

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,39 +63,33 @@ describe("MultiProvider", () => {
6363
describe("ConsumeContext", () => {
6464
test("consumes a context via use-function", () => {
6565
const Ctx = createContext<string>("Hello");
66+
const useCtx = () => useContext(Ctx);
6667

67-
function useCtx() {
68-
return useContext(Ctx);
69-
}
70-
71-
let capture;
68+
let capture1;
69+
let capture2;
70+
let capture3;
7271
renderToString(() => {
7372
<Ctx.Provider value="World">
74-
<ConsumeContext useFn={useCtx}>
73+
<ConsumeContext use={Ctx}>
7574
{value => (
76-
capture = value
75+
capture1 = value
7776
)}
7877
</ConsumeContext>
79-
</Ctx.Provider>;
80-
});
81-
82-
expect(capture).toBe("World");
83-
});
84-
85-
test("consumes a context via context object", () => {
86-
const Ctx = createContext<string>("Hello");
87-
88-
let capture;
89-
renderToString(() => {
90-
<Ctx.Provider value="World">
91-
<ConsumeContext context={Ctx}>
78+
<ConsumeContext use={useCtx}>
9279
{value => (
93-
capture = value
80+
capture2 = value
81+
)}
82+
</ConsumeContext>
83+
<ConsumeContext use={() => useContext(Ctx)}>
84+
{value => (
85+
capture3 = value
9486
)}
9587
</ConsumeContext>
9688
</Ctx.Provider>;
9789
});
9890

99-
expect(capture).toBe("World");
91+
expect(capture1).toBe("World");
92+
expect(capture2).toBe("World");
93+
expect(capture3).toBe("World");
10094
});
10195
});

0 commit comments

Comments
 (0)