Best practice working with reactive values inside context provider

I did some experiments using solidjs context. Context as value is not reactive in solid.js. It's a little different from props that are reactive - if you pass signals as props like a={a()} to Child, and access props.a - a is reactive. If I wrap the context value in a function and treat context as Accessor<OriginalContextValue> - it's reactive. If I use a store it's reactive too (but the update needs to be done differently). So is it considered good practice to use it with thunk (wrapping in a function)?
function App() {
const [a, setA] = createSignal<number>(1);
const [b, setB] = createSignal<number>(1);

// ✅ reactive
const contextThunk = () => {
return { a: a(), b: b() };
};

// ✅ reactive
const contextMemo = createMemo(() => {
return { a: a(), b: b() };
});

return (
<div>
<button type="button" onClick={() => setA(a() + 1)}>
a++
</button>
<button type="button" onClick={() => setB(b() + 1)}>
b++
</button>
// This is reactive because its contextMemo (as a function) instead of contextMemo() (as a value)
<AppFunctionContext.Provider value={contextMemo}> // inside `const context = useContext(AppFunctionContext)` and `const a = context().a`
<ChildWithFunctionContext />
</AppFunctionContext.Provider>
</div>
);
function App() {
const [a, setA] = createSignal<number>(1);
const [b, setB] = createSignal<number>(1);

// ✅ reactive
const contextThunk = () => {
return { a: a(), b: b() };
};

// ✅ reactive
const contextMemo = createMemo(() => {
return { a: a(), b: b() };
});

return (
<div>
<button type="button" onClick={() => setA(a() + 1)}>
a++
</button>
<button type="button" onClick={() => setB(b() + 1)}>
b++
</button>
// This is reactive because its contextMemo (as a function) instead of contextMemo() (as a value)
<AppFunctionContext.Provider value={contextMemo}> // inside `const context = useContext(AppFunctionContext)` and `const a = context().a`
<ChildWithFunctionContext />
</AppFunctionContext.Provider>
</div>
);
2 Replies
thetarnav
thetarnav2y ago
I usually do this
const value = {
get a() {
return a()
},
get b() {
return b()
}
}
// or
const value = {
a, // as functions
b
}
const value = {
get a() {
return a()
},
get b() {
return b()
}
}
// or
const value = {
a, // as functions
b
}
so the same as props - you just have to manually create the object, instead of relying on compilation doing this will merge the two "update channels" in to a single one
const contextMemo = createMemo(() => ({ a: a(), b: b() }));
const contextMemo = createMemo(() => ({ a: a(), b: b() }));
which can cause over-updating in downstream computations as you cannot now listen to a() selectively
nirtamir2
nirtamir2OP2y ago
Thank you very much!
Want results from more Discord servers?
Add your server