Reactivity of my component

I'm having problems with the reactivity of my component. In this example, the 'currentCplId' variable inside the createEffect is always updated, but outside of it, it is not updated. Why? And how to fix it? Can someone help me?
import { pageStore } from '@store/index'
const Component = (props) => {
const [ cpdId, setCplId ] = createSignal(pageStore.pageSettings.cplId)
createEffect(() => {
setCplId(pageStore.pageSettings.cplId)
console.log(cplId())
})
console.log(cplId())
}
import { pageStore } from '@store/index'
const Component = (props) => {
const [ cpdId, setCplId ] = createSignal(pageStore.pageSettings.cplId)
createEffect(() => {
setCplId(pageStore.pageSettings.cplId)
console.log(cplId())
})
console.log(cplId())
}
8 Replies
REEEEE
REEEEE3mo ago
Components don't rerun You have to use signals inside of reactive contexts like JSX or effects
peerreynders
peerreynders3mo ago
Understanding Building a Reactive Library from Scratch will likely help to shape your mental model. After that it should be clear that the last console.log(cplId()) isn't run in a place where it can "subscribe for updates" so it will only ever get the value right then and there. It's only within Solid's reactive primitives and Solid's variant of JSX running under render() that automatic subscriptions to reactive updates can be made.
DEV Community
Building a Reactive Library from Scratch
In the previous article A Hands-on Introduction to Fine-Grained Reactivity I explain the concepts...
Gabriel Viol
Gabriel Viol3mo ago
I studied the post a bit, did some tests, and came up with this solution. It works, but I wanted to know if this is the best solution in SolidJS?
const Component = (props) => {
const [ cpdId, setCplId ] = createSignal(pageStore.pageSettings.cplId)
const render = () => {
createEffect(() => {
setCplId(pageStore.pageSettings.cpdId)
})
return(
<Element cpdId={cpdId} />
)
}
return render()
}
const Component = (props) => {
const [ cpdId, setCplId ] = createSignal(pageStore.pageSettings.cplId)
const render = () => {
createEffect(() => {
setCplId(pageStore.pageSettings.cpdId)
})
return(
<Element cpdId={cpdId} />
)
}
return render()
}
peerreynders
peerreynders3mo ago
What is '@store/index'? - if it's a Solid store then import is a potentially problematic way to get it. - if it's a Solid store, it's already reactive (unless something broke it) and there is no need for the signal. - if it isn't a Solid store how would it be reactive inside of createEffect? - In Solid JSX is already an effect, so there may be no need for one. When I mentioned ''running under render()"
import { render } from "solid-js/web";
// …
// … this is the render() I meant
render(() => <App />, document.getElementById("app")!);
import { render } from "solid-js/web";
// …
// … this is the render() I meant
render(() => <App />, document.getElementById("app")!);
REEEEE
REEEEE3mo ago
There's no need to do that
bigmistqke 🌈
bigmistqke 🌈3mo ago
I think u misunderstood peer a bit. the post he shared wasn't about how to write solid code, but how to build something like solid, the library itself. We can tell you such things as components don't re-run but then it stays a very abstract concept, a rule we tell you and you must follow. By showing you the mechanism behind solid you can contextualize these rules until they stop being rules and they become more of a mental model. There is a 5 minute video version of the same content that I really like a lot https://www.youtube.com/watch?v=cELFZQAMdhQ&t=1s It's cool that solid is simple enough that you can explain how the library works under the hood and simultaneously implement a sketch of it in 5 minutes. It glosses over some details of course, but still, most of the big lines are there. It would be a hard time to do the same thing with react.
Gabriel Viol
Gabriel Viol3mo ago
Yes, this is my store. To elaborate, I have buttons on the screen. Each button has a value. Clicking a button stores its value in the store as CplId. When this CplId changes, an element corresponding to this CplId needs to be rendered. However, the button isn't within the same component that renders this element. Therefore, I achieve this with the following code:
const [local, rest] = splitProps(store, ['CplId']);
const [ itemActive, setItemActive ] = createSignal();
createEffect(() => {
const items = path(['props', 'children'], element.children[0])
const foundItem = items.find(item => item.props.cplId === local.CplId);
setItemActive(foundItem)
})
const [local, rest] = splitProps(store, ['CplId']);
const [ itemActive, setItemActive ] = createSignal();
createEffect(() => {
const items = path(['props', 'children'], element.children[0])
const foundItem = items.find(item => item.props.cplId === local.CplId);
setItemActive(foundItem)
})
peerreynders
peerreynders3mo ago
Seems context may be a simpler way to approach that (it doesn't have the limitations as the React version as all the moving parts are inside the reactive primitives, not the context value (which consequently never changes)). Example Note how there are two separate exports in order to maintain read/write segregation. - useLastEdit to obtain (only) the accessor - useSendLastEdit to obtain (only) the setter (… not really; it just makes sure that TypeScript yells at you if you try to use both successor and setter in the same component).
GitHub
solid-start-notes-basic/src/components/app-context.tsx at main · pe...
Basic client rendered notes app using SolidStart beta - peerreynders/solid-start-notes-basic
SolidJS
Solid is a purely reactive library. It was designed from the ground up with a reactive core. It's influenced by reactive principles developed by previous libraries.
Want results from more Discord servers?
Add your server
More Posts