Bro you hit the nail in the head with this one, the problem is, most of the time a search is not only a search, more often you also have extra filters for the query, and pagination, other times you also need to consider the load in the server so you have to add debounce, which a lot of devs won't be able to implement without introducing state. So that might be a good video idea, a full search tutorial, keep up the good work!
Long ago you made a video title something like "Lifting State Up" where you might have shown the same logic. But at that time I was new to the React ecosystem and did not want to feel overwhelming. But today I felt the need of this technic and was searching for the video but could not find that as "Lifting State Up" is an established jargon in the react world for almost the same topic. So, as I already have subscribed you, so I searched for your channel in my subscription list and wala, found that you covered the same topic in your last video also. Thanks a lot.
This info is actually useful for any project without relation to React or any other framework. Great job simplifying the problem and explaining it in a way that is easy to understand and solve.
Thanks for another great tip, Sam! I wanted to ask about your thoughts on how this might spam the back button history with a lot of intermediary state values, i.e. every keystroke. I know that `router.replace` vs `router.push` might be one possible solution, but let's say we wanted to stick with router.push, but to just have it be less noisy. One compromise might be to avoid updating the URL after every keystroke, and do some sort of debouncing. But here's the catch: Is it possible to keep the UI updates instantaneous (so NO debouncing there), but while having the browser entry be debounced? With this current approach it doesn't seem possible at first glance, and might require separating out the source of truth into two sources again?
I would go with `router.replace` as for mobile this would be a nightmare. If I were to go to a page, type in some search then swipe back to the previous page, I would expect to go to the previous page, not the previously typed character. This use case would also break in the case of no js or slow network and you could rely of tag to use a normal
I was also going to comment this. I would use router.replace here. I don't think he would have found this bug with router.replace since the back button would just go the prior page and not consider each keystroke. @samjohnston3416 makes a good point about mobile swiping back and forth.
@PRonTH-cam as for your question regarding debouncing, you would just debounce the onChange function of the input that’s calls the router.push or replace
I always use this pattern when it comes to lifting state up to URL. But in case of search inputs, I usually use debounced change and "replace" instead of "push", because a layman user thinks he should go one page back when they press the back button.
What if we need to validate the searchParam? Let‘s say instead of a string for a input field, we have a select input, with a defined set of values. What if the user provides a value that is not in the set of the provided values. How would you handle that? Show an error or redirect to a default value? Or both? Would love to hear your insights on that!
Great question! Typically websites ignore them, so I would parse/validate them and if it's not what you expect just treat it as if it wasn't there. So the variable in your React app would be the default (empty string in the case of this video).
Nice work, Sam! This looks great. I have a similar use case where I added search/pagination functionality to a table, but now I need to include two or more tables on the same page. What’s the cleanest way to manage multiple tables? Should I use separate page parameters for each table (e.g., table1Page=2 and table2Page=1) to allow for independent pagination and search, or is there a better approach?
could this get complicated to update the query string when there are multiple parameters? say there is two query params a and b...and two input fields for each query param respectively..........how could you easily only update the input field that was updated? My quick guess would be to use URLSearchParams?
now make this into a custom hook that gives you the logic to do this with *any* query param. usually it'd require a serialize and deserialize method, default value to remove the query param, and using the router as a patcher of k-v values rather than hard coded url
I''ve been working on this for over a year, you're on the right track. Add a throttled update queue to handle browsers rate-limiting URL updates, and you"ve got the `nuqs` package.
I thought the bug was that hitting the back button removed a single character from the URL instead of actually going back to the previous page as it's supposed to...
Yea, I think that should be the behavior. Using router.push creates a new entry into the history stack , router.replace would be more suitable in this scenario
Hands down, the best React instructor out there.
I would love if you have a full course on edge cases that I could buy.
Love this idea! Any you have in mind off the top of your head?
Bro you hit the nail in the head with this one, the problem is, most of the time a search is not only a search, more often you also have extra filters for the query, and pagination, other times you also need to consider the load in the server so you have to add debounce, which a lot of devs won't be able to implement without introducing state.
So that might be a good video idea, a full search tutorial, keep up the good work!
It is very important to add a debouncer as well. Otherwise, there will be too many requests to the backend.
Long ago you made a video title something like "Lifting State Up" where you might have shown the same logic. But at that time I was new to the React ecosystem and did not want to feel overwhelming. But today I felt the need of this technic and was searching for the video but could not find that as "Lifting State Up" is an established jargon in the react world for almost the same topic.
So, as I already have subscribed you, so I searched for your channel in my subscription list and wala, found that you covered the same topic in your last video also. Thanks a lot.
Please add regular videos for these kind of things. Its fun learning from you.
This info is actually useful for any project without relation to React or any other framework. Great job simplifying the problem and explaining it in a way that is easy to understand and solve.
I appreciate your authenticity and clarity Sam!
You are such an awesome educator. It's unreal!
Beautifully explained as always, thanks Sam!
Thanks for saving the day again man,this was a lifechanger as i had a bug like this😅
two-way flow and the source of truth explanation is very clear.
Please make more such videos on React and concepts like this. Love the video.
nice job Sam, funny enough i did this yesterday at my job!! I'm happy that we're getting state back to the url
Thanks for another great tip, Sam! I wanted to ask about your thoughts on how this might spam the back button history with a lot of intermediary state values, i.e. every keystroke. I know that `router.replace` vs `router.push` might be one possible solution, but let's say we wanted to stick with router.push, but to just have it be less noisy. One compromise might be to avoid updating the URL after every keystroke, and do some sort of debouncing. But here's the catch: Is it possible to keep the UI updates instantaneous (so NO debouncing there), but while having the browser entry be debounced? With this current approach it doesn't seem possible at first glance, and might require separating out the source of truth into two sources again?
I would go with `router.replace` as for mobile this would be a nightmare. If I were to go to a page, type in some search then swipe back to the previous page, I would expect to go to the previous page, not the previously typed character. This use case would also break in the case of no js or slow network and you could rely of tag to use a normal
I was also going to comment this. I would use router.replace here. I don't think he would have found this bug with router.replace since the back button would just go the prior page and not consider each keystroke.
@samjohnston3416 makes a good point about mobile swiping back and forth.
@PRonTH-cam as for your question regarding debouncing, you would just debounce the onChange function of the input that’s calls the router.push or replace
You should add debounce to your input onChange and instead of "value" you should use "defaultValue" of initial search value
I would also go with replace
Life saver😮
Thank you so much
I love your videos, man. Thank you a lot.
yay your back
❤ thank you very much, for all the wonderful videos
excellent video as usual. What course are you guys currently working on (I am a buildui premium member)?
This is such a helpful video!
Great vid! But should add a follow up on how to add a debouncer. Having to press back for each letter is horrendous UX, no one would ship that! 😅
can we also push on un-focus to make back thing work correctly? and let suppose we have more params
Awesome!! This was great!
I also implement the same thing with react query and Mui datagrid along with search it also handle the pagination.
I always use this pattern when it comes to lifting state up to URL. But in case of search inputs, I usually use debounced change and "replace" instead of "push", because a layman user thinks he should go one page back when they press the back button.
What if we need to validate the searchParam? Let‘s say instead of a string for a input field, we have a select input, with a defined set of values. What if the user provides a value that is not in the set of the provided values. How would you handle that? Show an error or redirect to a default value? Or both?
Would love to hear your insights on that!
Great question! Typically websites ignore them, so I would parse/validate them and if it's not what you expect just treat it as if it wasn't there. So the variable in your React app would be the default (empty string in the case of this video).
@@samselikoff Thanks for the quick answer!
Thanks. I will now start fixing my code.😆
Awesome video!
Nice work, Sam! This looks great. I have a similar use case where I added search/pagination functionality to a table, but now I need to include two or more tables on the same page. What’s the cleanest way to manage multiple tables? Should I use separate page parameters for each table (e.g., table1Page=2 and table2Page=1) to allow for independent pagination and search, or is there a better approach?
I'd probably use table[1][page]=1
could you explain why you use let instead of const for state variables etc?
can you please setup a stackblitz, replit or code sandbox so we could follow along?
love your content
Well done!
You should check out nuqs, a really interesting state manager, that's trying to accomplish what you are making in this video.
could this get complicated to update the query string when there are multiple parameters? say there is two query params a and b...and two input fields for each query param respectively..........how could you easily only update the input field that was updated? My quick guess would be to use URLSearchParams?
now make this into a custom hook that gives you the logic to do this with *any* query param.
usually it'd require a serialize and deserialize method, default value to remove the query param, and using the router as a patcher of k-v values rather than hard coded url
I''ve been working on this for over a year, you're on the right track. Add a throttled update queue to handle browsers rate-limiting URL updates, and you"ve got the `nuqs` package.
Thank you so much sam
Perfect!
thanks, useful video
thanks for sharing but in every character input it sends a request ?
So how does the back button actually work? I had assumed it works the same as opening the previous irl in a new tab
on which version of next does this work on ?
cause using nextjs 14 this will cause a fullpage reload so it is lagging when updating the url
Ooookay, I neeed to fix something my code . Thank you for let me know, now I have a bug 😅
Yeah, it's either denounce is used or an abortController to cancel subsequent request and improve the user experience and performance
@@adamjamiu6764 React Query already ignores stale updates so an AbortController wouldn’t change the behavior here
❤❤
I thought the bug was that hitting the back button removed a single character from the URL instead of actually going back to the previous page as it's supposed to...
Yea, I think that should be the behavior.
Using router.push creates a new entry into the history stack , router.replace would be more suitable in this scenario
But I don't want the back button behaving that way