S
SolidJS•5w ago
snorbi

How to extract common reactive code?

I have some common code that I want to use in multiple components, like:
const [currentTime, setCurrentTime] = createSignal(getCurrentTimeMinutePrecision())

let timer: NodeJS.Timer
onMount(() => {
timer = setInterval(() => {
const now = getCurrentTimeMinutePrecision()
if (!now.equals(currentTime())) {
setCurrentTime(getCurrentTimeMinutePrecision())
}
}, 1_000)
})
onCleanup(() => clearInterval(timer))
const [currentTime, setCurrentTime] = createSignal(getCurrentTimeMinutePrecision())

let timer: NodeJS.Timer
onMount(() => {
timer = setInterval(() => {
const now = getCurrentTimeMinutePrecision()
if (!now.equals(currentTime())) {
setCurrentTime(getCurrentTimeMinutePrecision())
}
}, 1_000)
})
onCleanup(() => clearInterval(timer))
What is the correct way to refactor this code fragment to a separate function and use it from multiple components? Can I just simply extract it as is, and return the Signal (or only the Accessor in case of my example)? E.g. what would happen if I call this from inside an effect? Can I somehow prevent it to be called from an ordinary function? Thanks.
5 Replies
bigmistqke
bigmistqke•5w ago
Yes, you can simply extract as is!
Can I somehow prevent it to be called from an ordinary function?
Wdym with this?
snorbi
snorbiOP•5w ago
Wdym with this?
I mean that somehow prevent it to be called from a non-reactive context. Is there for example, some Typescript typing "trick" that can check it at compile-time? Or isn't it that simple? 🙂 Thanks, I created this cute function 🤩
export function useCurrentTimeMinutePrecision(): Accessor<DateTime> {
const [currentTime, setCurrentTime] = createSignal(getCurrentTimeMinutePrecision())

let timer: NodeJS.Timer
onMount(() => {
timer = setInterval(() => {
const now = getCurrentTimeMinutePrecision()
if (!now.equals(currentTime())) {
setCurrentTime(getCurrentTimeMinutePrecision())
}
}, 1_000)
})
onCleanup(() => clearInterval(timer))

return currentTime
}
export function useCurrentTimeMinutePrecision(): Accessor<DateTime> {
const [currentTime, setCurrentTime] = createSignal(getCurrentTimeMinutePrecision())

let timer: NodeJS.Timer
onMount(() => {
timer = setInterval(() => {
const now = getCurrentTimeMinutePrecision()
if (!now.equals(currentTime())) {
setCurrentTime(getCurrentTimeMinutePrecision())
}
}, 1_000)
})
onCleanup(() => clearInterval(timer))

return currentTime
}
And it seems to work 😄
bigmistqke
bigmistqke•5w ago
No typing tricks. You can check if you are in a reactive context with getListener, but for ur hook it doesn't really matter too much. If someone accesses it outside reactive context it will just not be reactive. If you use eslint you will get a warning. As long as u prefix the hook with use or create
snorbi
snorbiOP•5w ago
Thanks a lot for the detailed answer! 🙂
bigmistqke
bigmistqke•5w ago
Ur super welcome!

Did you find this page helpful?