S
SolidJS•10mo ago
Shonty

How to trigger createEffect when navigating to the same URL ?

Hi, is it possible to trigger a createEffect that listens to location.search from the solid router's useLocation when I navigate to the same URL?
7 Replies
FelipeEmos
FelipeEmos•10mo ago
Your question has an interesting phrasing... what you do you want to do with that possibility? Maybe you should look at the problem at a different angle... so what's your problem? Have you considered something like just putting an even listener to whenever the router changes routes?
Shonty
ShontyOP•10mo ago
@FelipeEmos To add some context to my question, I have a lot of buttons that act as filters used in the url. When I click on values of buttons, I store those values in a signal object, and when i click on the "Validate" button, it change the url params accordingly. I decided to listen to location.search in a createEffect so it plays nice with the browser back button and reduce overall code complexity. My problem here is when i click on the value of a button, and don't click on "Validate" button but I click on "Reset" button instead to put the default value, I navigate to the url with no query params. But if the url is already the one with no query params, it doesn t trigger the createEffect, and don t reset the value of the buttons I previously clicked. I ask this question because there is an option similar with signal with const [something, set_something] = createSignal<string>('', { equals: false }); where you can trigger reactivity even if you set the same value Here is a simplified code of my button component
const Button: Component<{button_name: string}> = (props) => {
const location = useLocation();
const [button_value, set_button_value] = createSignal('');

createEffect(on(() => location.search, () => {
const search_params = new URLSearchParams(location.search).get(props.button_name);
set_button_value(search_params ? search_params : '');
}))

return (
<>
{/* Some code here */}
</>
);
}
const Button: Component<{button_name: string}> = (props) => {
const location = useLocation();
const [button_value, set_button_value] = createSignal('');

createEffect(on(() => location.search, () => {
const search_params = new URLSearchParams(location.search).get(props.button_name);
set_button_value(search_params ? search_params : '');
}))

return (
<>
{/* Some code here */}
</>
);
}
A solution to my problem could be to change the url with a dummy path that is not the default url, and navigate back to the default url to trigger the createEffect, but it doesn't sound clean
FelipeEmos
FelipeEmos•10mo ago
I don't think it's worth it to go for the "navigate just to retrigger" thing as you suggested last.... I agree it's not clean, a little hacky If you wanted to solve things in a similar "not ideal" solution you could put a manual reset trigger on your specific action that is troublesome. Here's a code ChatGPT created when I prompted our conversation
const Button: Component<{button_name: string}> = (props) => {
const location = useLocation();
const [button_value, set_button_value] = createSignal('');
const [resetTrigger, setResetTrigger] = createSignal(0);

const updateButtonValue = () => {
const search_params = new URLSearchParams(location.search).get(props.button_name);
set_button_value(search_params ? search_params : '');
};

createEffect(on([() => location.search, resetTrigger], updateButtonValue));

// Function to handle reset
const resetFilters = () => {
// Navigate to the URL without query params
// ...

// Trigger the effect
setResetTrigger(count => count + 1);
};

// JSX and other logic
// ...

return (
<>
{/* Some code here */}
</>
);
};
const Button: Component<{button_name: string}> = (props) => {
const location = useLocation();
const [button_value, set_button_value] = createSignal('');
const [resetTrigger, setResetTrigger] = createSignal(0);

const updateButtonValue = () => {
const search_params = new URLSearchParams(location.search).get(props.button_name);
set_button_value(search_params ? search_params : '');
};

createEffect(on([() => location.search, resetTrigger], updateButtonValue));

// Function to handle reset
const resetFilters = () => {
// Navigate to the URL without query params
// ...

// Trigger the effect
setResetTrigger(count => count + 1);
};

// JSX and other logic
// ...

return (
<>
{/* Some code here */}
</>
);
};
It makes sense Buuuut maybe you could just change the dependency to look for the whole location, does that work? I'm curious Something like changing your code from
createEffect(on(() => location.search, () => {
const search_params = new URLSearchParams(location.search).get(props.button_name);
set_button_value(search_params ? search_params : '');
}))
createEffect(on(() => location.search, () => {
const search_params = new URLSearchParams(location.search).get(props.button_name);
set_button_value(search_params ? search_params : '');
}))
to
createEffect(on(() => location, () => {
const search_params = new URLSearchParams(location.search).get(props.button_name);
set_button_value(search_params ? search_params : '');
}))
createEffect(on(() => location, () => {
const search_params = new URLSearchParams(location.search).get(props.button_name);
set_button_value(search_params ? search_params : '');
}))
Shonty
ShontyOP•10mo ago
It's a great idea but it doesn't seem to work I found this solution where I navigate with navigate(default_url, { state: reset_signal() }); and listen on location.state in addition to location.search, but it might have some weird edge case that I didn't think of. For instance, when I hit the browser back button, the createEffect run twice if I previously reset the buttons, but in this particular example, it still work as expected on the user interface
createEffect(on([() => location.search, () => location.state], () => {
const search_params = new URLSearchParams(location.search).get(props.button_name);
set_button_value(search_params ? search_params : '');
}))
createEffect(on([() => location.search, () => location.state], () => {
const search_params = new URLSearchParams(location.search).get(props.button_name);
set_button_value(search_params ? search_params : '');
}))
FelipeEmos
FelipeEmos•10mo ago
Nice, this seems pretty decent The "run too much" aspect of it is probaby negligible and you shouldn't be too worried about edge cases in my opinion If this starts giving you some problems or you want to be extra careful about such "edge cases", you can always do a diffing yourself! That should be easy, you have to track the last time you've run the effect and do an early exit if necessary. Maybe save the "lastUrl" in a variable and if the current "url" is equal to the "lastUrl" do nothing, just early exit. Then if it changed you update the "lastUrl" and do your computation 🚀
Shonty
ShontyOP•10mo ago
Thanks for your help 🙂
FelipeEmos
FelipeEmos•10mo ago
Your welcome, glad I could add something haha 🙌
Want results from more Discord servers?
Add your server