-
-
Notifications
You must be signed in to change notification settings - Fork 98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useSignalEffect should execute after changes have been applied to the DOM #228
Comments
That's a very good point. I hadn't thought about the interplay with ref's. |
Hmm, that makes sense. I guess the sync escape hatch is possible but leveraging the commit options hook would allow us to immitate the timing of a regular useEffect |
If you give me some instructions, I can work on the PR. |
Ran into this as well, I ended up creating a reactive ref that seems to do the trick and essentially would work like a const node = useSignal<HTMLElement | null>(null)
const ref = useCallback((refNode) => (node.value = refNode), [])
useSignalEffect(() => {
if (open.value) node.value?.focus()
}) If this could somehow work like useEffect out of the box though that'd be awesome! |
@JoviDeCroock, @marvinhagemeister: any idea how to implement this? I can work on it. |
I would say that it would work like the following, we introduce a second variable an object containing mode/timing as a key with three values
Would this be sufficient to work on it? Imho we could omit layout as an option for the time being until folks find a use for it. |
Thanks @JoviDeCroock.
I can't find
Hmmm... I guess the problem is how to delay the execution of the function useSignalEffect(cb: () => void | (() => void)) {
const callback = useRef(cb);
const firstTime = useRef(true);
callback.current = cb;
useEffect(() => {
return effect(() => {
if (firstTime.current) {
// First time
firstTime.current = false;
callback.current();
} else {
// Subsequent times.
setTimeout(() => callback.current(), 1000);
// It doesn't work because the callback will run once the computation
// (`effect`) has finished.
}
});
}, []);
} So, is there an API to delay the execution of
About that: so, right now this is the code of function useSignalEffect(cb: () => void | (() => void)) {
const callback = useRef(cb);
callback.current = cb;
useEffect(() => {
return effect(() => callback.current());
}, []);
} And it would accept a second argument, like this: function useSignalEffect(
cb: () => void | (() => void),
mode: "sync" | "layout" | "commit" = "sync"
) {
// ...
} Then, the implementation for each mode would be:
|
Is this still an issue? |
We have our own implementation of useSignalEffect in WordPress that has been working well so far. |
The callback passed to
useSignalEffect
should be executed after the changes (if any) have been applied to the DOM. Otherwise, it won't be a direct replacement foruseEffect
.For example, people expect this to work, even if
ref
appears whenopen
switches fromfalse
totrue
, becauseuseEffect
waits until changes have been applied to the DOM:But with the current implementation of
useSignalEffect
, the callback runs before the DOM changes, and thereforeref.current
may not exist yet:Full example in StackBlitz.
Other reactive libraries introduce a
tick
function (Vue, Svelte, Alpine), but I'd prefer ifuseSignalEffect
could mimicuseEffect
because the familiarity and ergonomics are better. I.e., access to signals after thetick()
call are not tracked.The text was updated successfully, but these errors were encountered: