Coding with Kent: Remix Examples

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] yo what's up i am live streaming again so it took a little bit of a break i was working on some stuff that i couldn't live stream and uh now i'm working on stuff that i can't so i'm gonna be doing some live streaming you are welcome to uh to join the discord where we'll do chatting and whatnot um and the discord uh for this because it's a remix specific live stream is the remix discord and i put a link to the event for today's live stream in the description of this video so you can get a link directly to it let me just grab uh yeah live stream chat that's where we're gonna be and let me share my screen um oh i sure hope i didn't show any keys there i don't think i did hold on a second let me uh let me close stuff really quick uh okay yeah no private keys so that's good um let me close that i'm pretty sure we don't want that oh man i've got so many things open i did i was not prepared for this live stream uh normally i close all these windows ahead of time and there are some keys but that's just my test stripe key so that's like probably no big deal okay cool now we're ready to share my screen okay so the first one i'm working on is infinite scroll and i've actually already built this and worked on this um already so we should be okay um i'm just going to drag this add folders copy folders that's what i want uh okay i didn't copy over the known modules because it would take longer probably to copy than to just install i don't know maybe not but yeah there we go cool so let's take a look at package.json make sure we're on the latest uh i believe 1.0.6 is still the latest we do have an experimental build but we can just go with the latest this is within the remix examples or the remix repo in the examples directory and this is for infinite scroll so um if we look at the app routes index this is where all this stuff is i'm guessing eslint is complaining because we added all these files after it booted itself up this lens is weird that way but it looks like that's not the problem um oh right it's this thing uh there we go save and autofix that's nice thank you okay sweet uh and let's i'm gonna get rid of some of this stuff that's a little confusing um but let's at least get this thing running sweet so there it is it does run and it updates the url and i think that is pretty stellar um one thing that i needed to change about this was um let's see tan tanner linsley react virtual i'm pretty sure whoops um i'm pretty sure he released a a newer version that has something that i need 2.10 yep so let's run that install again and let me find that issue can you all hear my kids they're like they're cleaning but they're playing this cleaning game and it's fun but um can be a little bit loud um sweet yeah oh by the way i didn't show this earlier but oh i should probably start this start oh it started okay good but yeah so this is where we're gonna be chatting in the live stream chat so in case you didn't know that's where uh i'm gonna have that open uh i think the youtube probably has the live chat on the side i am going to ignore i think it's on this side i'm gonna ignore that um because um it's just easier for me to manage uh the discord and i like um i just like it better i don't know should i let's take a look here um in fact you know what i should do is i should post a link to the live stream there it is hello friends um yeah let me post this to the discord so folks can can grab that um yeah i guess i guess i can okay we're going to try it i've just had some bad experiences with youtube not caring about people being really terrible people on here but we're going to try this and i will have both the discord and the uh youtube open the youtube live chat so we'll see hopefully y'all are nice um okay let me find the issue uh ssr support and he was set he said it was solved by this use observer thing um this pr initial wrecked okay cool so that's what i'm looking for initial rect um that's not on here but we do have a docs search docs boom initial rect spinner huh that's interesting try again nope no dice okay it's possible it was not documented um api reference there we go initial rank um okay so it's optional defines initial wrecked size of list can be used for server side rendering that's exactly what i asked for it and um yeah so our initial rect for uh use virtual um i'm guessing this is some sort of number uh nope it's an object width and height that makes a lot of sense uh width uh i don't actually care about the width but the height um i can say uh what the height is going to be um because i specify it to 800 pixels so now um on this oh it's not running there we go i have an alias nrd and anytime that's for npm run dev and anytime i run that i always say in my mind nerd okay cool so let's come back here we'll refresh and here's the cool thing because it's server rendered we can look at we've got item 10 boom it looks like it goes as far as item 23 which is exactly what i need sweet so it's server rendered the whole list that's great that's what i'm looking for um cool and then yeah and then you can scroll from there okay sweet so then the next thing is i want to be able to hit refresh and have it scrolled in that position um yeah this is currently not supported so yeah this is this is unfortunate we don't have a mechanism for restoring scroll position here but i think i can build it myself so that's what we're going to do here is is we're going to restore the scroll position so this will probably involve a before unload right here on before unload oh use before unload and so in this hook i will say hey before you unload i want you to persist the scroll position of this scrollable thing into session storage um in the browser and then in a use effect before react query takes over i'm going to say tell it to scroll to a specific spot i'm not sure if react query gives me those apis i know that like i can control scrolling but i don't know if i can do that before i don't know we'll we'll see i might be able to make this work i think i will we'll find out okay so um actually you know what we don't even need to use these before unload to see if it'll work so i'm gonna get rid of this um and we're gonna say react use effect um yeah okay um and we want to take our parent ref and this is going to be you know right here uh current and yeah scroll top start what is start oh okay yeah sure times 35 wow that is nuts that's not what i was expecting uh to do but that works that's so cool um okay and our start is changing over time we actually only want to do this on the initial render so we're going to grab our initial start and this is going to be is there a list of examples i'm covering no um i um i will get as far through this infinite scroll as i can um and like i s um i mentioned i should say that this isn't uh let me educate you uh live stream this is uh i'm working on something feel free to watch um that's what this is oh and ryan is watching hey there ryan he's saying you'll want to use layout effect when you yep that makes tons of sense so here's how you do a ssr layout effects because this is running on the server uh use ssr actually you know what i've got in my clipboard use ssr there it is so you say type of windows undefined well in that case our hook does nothing it's just a function otherwise it's use layout effect and this is how you work around the ssr warnings this is like i know what i'm doing um but one problem with this is you're not going to get the eslint warnings right here you could configure eslint to do that though um okay so um ryan was typing something else he's leaving now just popped in hi there see ya um okay cool so we won our initial start and so this is our little hack to do that i could do a ref but yeah this works just as well so here's our initial start and hopefully we won't need to do this in the future by the way in the future remix will have an api for you to say hey this thing that's scrollable i want to restore this thing's scrollable position when you navigate around so in the future we will support that and so you won't have to do all this nonsense okay um so we can say if that's not a thing then let's just early return that should never happen um as long as react continues to work as it should but typescript wasn't happy about that so we will make typescript happen okay so we'll set the scroll top to the initial start times 35 that's what our our size is for everything um and actually that should work um yeah let me think uh yeah that should work hold on a second so if i come down here and my start is at 80 then there i am at 80. it changed my query string so that's weird i'll have to figure out what that is about but here if i go to 600 boom i'm at 600. so we can make this better though by not just restoring it to the start but instead restoring it to the position that we put in local storage recession storage or whatever um so uh yeah that's cool that ended up working out nicely um so yeah on use before unload we'll say um okay yeah that makes sense uh this needs to be in a used callback bring that in with remix uh and session storage dot stuff dot uh let's see scroll position uh scroll top let's i actually like calling the set item directly so this will be our infinite scroll top and we'll set it to the parent ref current scroll top there we go and um yeah i guess we i don't care to stream sure why is this complaining it is complaining because oh it could possibly be undefined all right fine we'll just do this if there's not a current then we'll return and now you won't be so mad and i don't think i need to to string that oh i guess i do typescript wants me to string it but it would it would string a fine fine um okay cool we don't need that there so that's sweet and then instead of the initial start times 35 we can say the session get item yada yada actually i wonder session storage come on i'm waiting for co-pilot to figure it out get item [Music] no oh there it is infinite scroll top or zero i guess here i don't want to bother with it if we don't have a value so whoops so let's say infinite scroll top and if we have one uh or if we don't have one then we'll return um yeah otherwise we will number the infinite scroll top there we go stellar all right let's see if that works i don't know what this was complaining about um but probably doesn't matter there we go okay so then we scroll down and we're like part way through 470 we refresh and there we are that's what i'm talking about look at that now i we need to fix this um flash of uh of that loading state because it should definitely not be doing that um because it's server renders but it looks like we are doing a uh data or a a fetch here looks like we're doing two of them one where the limit is 200 and the start is zero and then another with the start at 760. and that's probably why we're getting that flash of loading state so um our search params initialize that wonder why it is [Music] um yeah i have to remind myself how all this code works so i land on here and it is updating the url so let's take a look at our uh set search params where we're doing that so that's happening in this use effect that makes sense uh if the needed start is not equal to the start so i'm guessing um that's interesting yeah so sorry for the person you just asked what i'm working on i'm working on an example for using remix with infinite scroll and um so it works and it works great right now it updates the url i think i'm going to add a session and store those values in a cookie so that you don't even update the url but you still get infinite scroll that relies on the disk cache for the from the browser and will restore scroll position um that will be that will be so cool um but uh yeah for right now um i am um yeah i just finished restoring the scroll position now i need to figure out why the um this set search params is being run and i think i have an idea but let's go ahead and add a debugger right here oh my goodness i just turned on my screen saver there we go uh hold on a second um i'm gonna just helps with something really quick i can i just need to do something for my kids here really quick they've been working really hard to clean the downstairs so they can watch lion witch in the wardrobe so we're gonna turn that on for them really quick my wife says that their job is done they've been wanting to watch this for a while i don't know why but yeah we've got this like old cartoon lion witch in the wardrobe that i used to watch when i was a kid all the time and so i i found it on like amazon or something the dvd there we go um i love it i think it's awesome i'd watch it with them if i weren't working right now um okay sorry i just noticed a bunch of notifications that i need to clear okay so we've got our debugger and there we are somebody messed up the chrome dev tools because when you land on a debugger it doesn't update your sources location anymore you have to click on this which is really annoying i don't like that but it is what it is so this is interesting i was expecting that on the server render you'd actually see all the items in here but it's not rendering those so that is unexpected um we'll have to see why that is happening um so here's our start that makes sense that's where we are there uh the needed start it's saying is zero um so that is the reason why we're setting the search params to zero that's kind of what i suspected so um yeah okay so then here we i actually need a debugger right up there to walk through how this is calculated so let's start over okay so hold on a second that's there we go okay that's interesting the first time it didn't render anything um but nothing too okay so on the server render it's actually showing nothing to see here so that also is something i need to look at um it might be the same uh same problem uh this is dank mono um this is my font okay so we're gonna step through um our first virtual item is at key 0. so for some reason it is starting us out there so i think i need to i think the solution to both the server render and the client um update is i need to tell react virtual uh this use virtual hook where we're starting um yeah where that that start is and i'm not sure how um yeah how possible that is with their api so we'll see um we've got sides over scan yeah horizontal scroll to function initial rect and this is the thing that they added for me so hooray use observer okay yeah i don't think that's what i want um we got padding key extractor range um i don't think that's what i want use window observer i don't think it's what i want either hmm yeah that's not it maybe i do need use observer [Music] so i get the parent ref will this even be called on the server i don't think it will um so hmm i think i may need to do a little bit of trickery to work around some of this stuff so uh in my debugger here where am i so i do get my start the lower boundary um yeah so that's like the bottom of the list once you hit there then we need to move the start um and the first virtual item index is zero um and i get that from row virtualizer which is coming from use virtual hmm this was really easy until i wanted it to be cooler than any other virtual scroll thing that you see in the real world where you can refresh and be right where you are look i go to twitter and like they're the exam the perfect example of you know scroll scroll scroll virtualization wow that's amazing and here we're loading more and then i hit refresh and i'm right back at the top so twitter doesn't even do this and you could argue that maybe that's not what you you would want on twitter like sometimes you hit refresh because you want to start at the top although they do have other mechanisms for getting you to the top so i would say it would be kind of cool if i could hit refresh and be restored where i was so we're going to make this cooler than any other infinite scroll you've seen before but it may require um some trickery so um yeah so we've got our start we've got our limit and i need to say if i think it's if we have not hydrated yet is is what we need um which i think actually maybe i can just have a if it's not mounted then don't um do this set search program so if this is the first time that we're calling this use effect then don't bother with the set search params um yeah so like what i could do first render or yeah true let's just try this maybe we can we could probably come up with something that's better so if first render then actually false but return yeah let's see what that does uh oh we got it here let's turn off the debugger okay and i thought i turned you off what the oh huh pretty sure that when you do that even debugger statements won't stop you but okay there we go so we refresh boom yeah look at that oh my gosh okay i did see a bit of a flash of loading state so let's slow down the network and see if there is some sort of weird loading thing going on so i'm going to scroll down we'll go go a little ways oh man that's that is interesting huh yeah so it is on a slow network connection if we scroll really fast on a slow network connection then we're gonna get this loading more so this is just the index uh this is the actual item itself and the item is item space index and so that's why you're seeing these two numbers and that's why you get loading more for the item but then you still see the index because we know what the index is just by scrolling okay anyway um it's pretty cool though like what's what's really cool is i'm not managing any sort of cancellation of requests or whatever as the user scrolls and they scroll past that data we're like oh i guess i don't need that anymore so i'll cancel that request we don't have to worry about that as users of remix ah that's so cool um yeah and then things can be served from the disk cache yeah we need to figure out this favicon problem too uh for some reason it's re-fetching the favicon as we're updating these search params i think i kind of have an idea of why that's happening um and it may involve a fix and remix but maybe not we'll see okay cool anyway um so on a slow network if i hit refresh i should be at 3181 on the server render huh that was interesting it was really fast i'm pretty sure i still saw a loading state though so like it flashed uh so here you know what here's what we need to do um needed start and start okay so they are the same so it's not updating my um my query string right here and i i can see that it's just not uh showing me that okay cool um yeah so uh darius you're you're right being able to uh to link to a specific scroll position would be really cool especially like on a dashboard or something you're like hey i was looking at this thing and um and so if if we're like start let's say you're on on github looking at all the commits and you're scrolling and they implemented infinite scrolling because that's a thing you can do and and so they they did that and you scroll in your scroll and scroll and so instead of the start being just an index it's actually a commit and so um you could just hand that off to somebody else and it will boom uh just stick you right where where you want to be that actually would be a sweet feature right now they're doing pagination that's the demo i'm going to build next and that's way easier than this that is way easier um so yeah the specific thing that i'm building i'm working on making it so people are really successful with remix that's the thing i'm building success with remix okay so we're we're not updating the search params but for some reason well and we're not making a fetch request either that's um yeah that's what's really odd that i'm getting that loading state so here let's slow down our uh where is that there we go our network or our cpu just see if i can see that yeah it says nothing to see here why is it doing that so we get nothing to see here oh right if our transition state is loading um then we say loading more item.value so if if there's an item they will display the value so apparently there's no item but the item comes from the data which is um coming from our used loader data which will always be there um so we should be seeing the item value transition state is loading then we're loading more but in our case it was nothing to see here is what it was hmm okay so there's probably something funny between the start and virtual row index so let's oh that's gonna log a bunch um yeah let's do this we'll log state is initial at start right or idle or something yeah so the state um this transition state is going to be idle yeah but it shouldn't even get this far it should stop right here and be like oh i've got the item value so the item is undefined that's probably what's going on uh so we've got this array of items um and i'm just not sure i there's something wrong with the start minus this virtual row index is what's going on um but i've just got like a bajillion of those things so we're going to console.log um the start which is i i expect that to be what i what i want it to be but the virtual rows um items is probably not what i want it to be um yeah so here we get it with the server render which is good so that's interesting we're getting index at zero oh right no that's what we want because um we only have so many on the client at any given time and as you scroll we we clear those out and put new ones in and so the first one will always be index 0. that's why we're doing this absolute value difference between start and index and so this should be data items at index 300 or 3120 um which i think is correct so our data items hold on a second let's look at our um data as well [Music] huh oh right that's that's our items i'm looking at our data okay got our id yeah so these are all index zero so this math absolute value for start and virtual minus virtual row index is going to give us um i think that um i think there's something wrong here that yeah that explains why it's saying there's nothing here is because um we're looking for data items at index 3120 but we only have 200 items so of course it's not there but then um here let's let's just refresh here really quick yeah okay so that's that's our our document right there um so then something happens to change our the way that these things are calculated so on this final render when we when everything's lined up properly our data items is still an array um starting at index zero and our items here the index there it is yeah so before we're hydrated the index is actually set to zero because um yeah because react virtual doesn't know um where we are in the window and so it just initializes to zero so we need to be able to tell it where we are in the window on the server render and that currently is not supported by um react virtual i believe um yeah if i knew this what better this code base then i'd maybe be able to do this let's see how bad that no that's actually not too bad let's see if we can figure this out um scroll top okay scroll key scroll to function that makes sense um [Music] let's see index there we go measurements index key extractor that's the key yeah so i measurements there it is so pending measured cash indexes ref wow tanner my man you put a lot of work into this stuff i'm so glad that he's doing this stuff latest draft pattern right there boom cool except he's doing a side effect in render whoops put that in a layout effect [Music] um oh this whole thing is the memo sorry i was thinking that it's just this first part okay so [Music] yeah let's see hmm [Music] yeah i'm not sure i equal min okay yeah so that's where the start will be well and that's minute zero pending measured cache indexes ref and that's this react use ref array okay so then we have this measure ref um for the items let's see measure ref yeah i'm just trying to see if there's a way to to not work around react virtual here but it looks like that is not um yeah what i'm looking for is not possible so here their measure graph says if there's an element which on the server render there won't be uh then we're going to do all this measurement stuff um and i suppose otherwise um well i guess otherwise it's probably never called that's interesting i don't even see it anywhere else on here what is measure f for oh that's for dynamic measurement rendering oh okay so we can override this a bit uh this so this is the default uh measurement stuff but it's never called i don't know maybe it's called in one of the other files um but i don't think that's what we're looking for yeah we we've got our measurements uh which is reffi or memo'd memoized and we just need a way to set this min and that is only set within the measure ref and measure f i still don't know when that's called so let's let's find out that i think that is actually relevant so um there are only two other files in here i don't think it's that one but yep um you know what uh so i i showed my use ssr thing um if window is not defined um wait if window is not undefined and use layout effect oh right yeah so if we're on the browser use that effect otherwise use effect this actually this is useless because if window's not defined then the use effect will never get called anyway so you can always you can just do an arrow function right there yeah it works um cool just notice somebody said that they're going through epic react good thank you that's awesome i'm glad to hear that um okay so anyway we're looking at use rect measure huh measureref is never called anywhere okay so this is i've just been nerd sniped how is this work uh react virtual dist um oh shoot i don't know which one of these we're using probably development um measure ref am i supposed to be calling measure ref okay hold on maybe he's got documentation huh okay let's just look at a couple oh variables probably where it's at view source nope okay here we'll look we'll just look it up here measure wrap oh okay so this is so that i can specify uh hold on a second measure okay so i can put this on an element and that element can have a variable size and react virtual will measure that element when it is rendered to the page and that's how it will determine what the scroll size should be okay cool so no that's not what i need um i don't need to use that api okay cool so i understand that um so i'm still and that will not get called on the server render anyway so now that we figured that out no there's not currently a way to do what i'm trying to do with react virtual as soon as i'm done i'm going to open an issue and say hey here's this workaround stuff i've got to do would be really cool if i didn't have to do that and see what they have to say tanner will probably be all over that in fact i'm going to lunch with tanner tomorrow because he and i are friends he's great um i'm actually really looking forward to that uh okay so utah's the best come live in utah there's all sorts of cool people here uh so we're gonna have to work around this and this will be okay because um we actually already um work around this with the first render thing so we know that it hasn't rendered yet now this is not um yeah like maybe it's not kosher so just to make it so that people don't judge me i'm going to switch to a ref for this or actually we could do yeah it'll be a ref so is mounted ref react use ref false and then we'll come down here so if we're not mounted then we'll say true and actually you know what this should probably let's just put all this in its own little section here react use effect there we go we can get rid of this first render nonsense and um here's the here's the kicker we need this to run um last i'm pretty sure they run the cleanups in reverse order and the effects in uh the order they appear so we're gonna want this to be actually at the bottom here because we need this to run first um okay so if it's not mounted then we'll return otherwise we can do all this stuff okay so that allows us then to say if we're not mounted and we're either on the server render or on the client now what's interesting oh no yeah the server render is also messed up so in either case before we're mounted uh react virtual doesn't know where um like what our index should be and so our virtual row index is going to be zero and so in that case we don't need to subtract the start we'll just go with uh with that so our index then will be if we're is mounted um it will be this otherwise it will be um just the virtual row index and then we can stick that i'm pretty sure this will work let's see what happens okay now that's interesting um that now yeah that is uh not going to show up in anything real i don't yeah i wouldn't expect that to ever show up in anything real but you'll notice that we start out with uh oh well i guess it happens really fast unless you're throttled let's do 6x slowdown yeah so you see it starts with zero at the top and then it updates so the reason that's happening is because uh we're rendering the index right here uh the virtual row index uh if we render the index then that'll fix that well i thought it would hold on why is that not fixing that um because yeah so if we're mounted then it's um the index is going to be the difference of the two otherwise it's the virtual row index so yeah this is actually not going to be the index this will be [Music] index indexing the whole data the whole whole amount to data which means that this will need to be that index plus the start that's what we're actually trying to render there we go and that is not good i don't know why it's having me bump around oh i do because we're using the start ah dang it ah um okay so i just noticed there's a bunch of chat here let me take a look um is there any way to know a div height and width before it is rendered so i can use a bin stack algorithm to stack items efficiently yes if you set it explicitly then like i'm doing here i'm i'm saying each one of these is exactly 35 pixels tall so i know that that's how tall it's going to be if it's dynamic though you cannot do that before it's rendered um but react virtual kind of manages that for you just won't work from the server render so something to yeah unless you want to simulate the layout in a node so that you can calculate what the heights are going to be you all you can do is your best estimate um okay so uh hold on yeah i'm actually kind of confused so 3120 because that's where our start is but we should not be rendering 3120. our item oh right because we're going because those indexes yeah shoot because we're okay so here's here's the window or the all of the items starting at 3120 right here i don't know if you can see both my hands yeah here we go so 3120 is right here is that the way i'm mirrored so left to right yes that's right okay so here's here's where we're at um 3120 is right here that's that's the whole thing 3120 to um 33 20. we have 200 items and then we're in this window right down here that we're scrolling around inside of that and when we get too close to one side we'll we'll add more if we get too close to the other side we'll add more and so within this window we are um oh whoops that was a mistake um within this window we're starting at 31.81 that's where we are at in a scrolled position and oh man um and so on the server render 3120 oops yeah there we go 3120 is all we can do because we don't know where we are in the scroll position that is actually stored in session in the session in the browser um but we could put it in a cookie session and i wanted to do that anyway for the the url so here's what i think i'm gonna do i'm gonna make two demos one of like here's the infinite scroll that's like your normal thing and it's really easy it doesn't update the url it doesn't restore scroll position stuff just to show that like your typical thing is not complicated at all but because we have remix we can do some other cool stuff it just requires a little bit of extra work so um i'm going to stop where we're at right now i'm i'm pretty sure we can solve this problem um and also like the little bit of extra work um also has an impact on um the um there was something else i was gonna say about that uh yeah forgot anyway it's not as nice but it's way oh yeah it has some constraints because you have to do your best guess on the server render and for us we know like we're setting it to 35 but if it's dynamic then you're going to have to just do your best guess which you end up having to do anyway um so it'd probably work out anyway um i i foresee people actually being able to use this use both of these so let's stop uh with this one we'll build like here's the simple example of infinite scroll here's the advanced example of infinite scroll um so let's do that i'm gonna come right here we're gonna say uh advanced or yeah advanced tsx we'll have a simple tsx and then our index will just link to those two and you can choose which one you want to look at okay so we'll stick all this in our advanced and in our simple and then let's um yeah remix component index route we have no data here we're just gonna have some links um index route uh okay infinite scroll demo and this probably makes more sense to put in a p tag we'll say um there are two demos here the first is um uh first shows how to do this in a simple way that's pretty standard for this this type of um user experience you have around the web the second is a bit more advanced but a um much better user experience um pick your i don't wanna say pick your poison but pick your preferred method uh okay so then we'll have a link two advanced and let's see simple sweet and then we'll have that from remix and boom let's put this in ul um uh for goodness sake there we go and eyes for both of those i mean nice try co-pilot that needs to be a two close call or you could have done better that's okay simple advance all right let's go with the simple first huh that's interesting why is it uh huh that's weird yeah it uh it started me at 3120. i don't know why i did that oh it's actually it's because it's stored in my session storage that's why uh we need to clear that session storage or something um yeah that brings an interesting point um when do you clear that probably on unmount yeah that would make sense um yeah let's let's fix that in advance we're not going to do that in the simple one um uh we could do that in here there it is so that'll fix that so then if i go here and then um we only want to restore it when we're hydrating we don't want to restore it when we are um when we're doing a client transition and this reminds me of the problem that we faced with the login modal in my last live stream when ryan joined us and that that was fun uh was a bit of a head scratcher but uh yeah there's an easy way to determine whether you're hydrating or client rendering and that is if you um actually there's uh it occurs to me um yeah well yeah the easy way to tell is if on your initial render is the dom um already in place is the dom already there um are the elements there and if they are then you're hydrating so um we only want to do this if we're hydrating so um let's we could probably put um yeah let's uh yeah you know what sometimes it's easier to think about things in isolation in a hook so use is hydrating and this is not going to be state this will be [Music] probably just a value that we return query string and we'll say if type of document so pro tip actually this should be document because in dino window is defined it's going to blow up everything document is not though so pro tip don't use type of window undefined anymore use document because otherwise your stuff won't work on dino so if you're like writing a library stunting so anyway if document is undefined here and actually you know what let's let's take this um there and we'll make this is server render and we'll just reuse that that'll work so if this is a server render then we'll return false because we are not hydrating um if the um the dom is already if the dom is not already there so um yeah we'll we'll we're going to hack this a little bit is uh dom is there react to use state we're going to do this because i don't want this to run on every render i don't want to query the dom every render so we're just going to do this here and we'll say document query selector query string and we'll boolean that thing oh and it's getting mad at me because of this so we'll just say this um if it's um not the server render and that there we go now you're not going to get mad at me so um yeah if the dom is there we've got our query string um yeah actually i think this is it i guess probably something better now because i've got my server render um is hydrating is probably more appropriate so um if we're not on the server render then we are not hydrating so that makes sense so is hydrating as false if we're not if we're server rendering um if we're not server rendering and the document query selector returns something then we are hydrating uh if if this ends up being false and we're not so that works out yeah okay cool so let's do this return zero there we go ah okay i hate that let's give it a variable name there we go that's a little bit better okay cool so um now we know hydrating and we're looking for a um an element that we can um that like we can look for a have a some sort of query string so well i guess we can just say list um let's do yeah let's uh yeah data um infinite or let's see hydrating um uh it's like our our signal sure i think it's probably stupid but that's okay i think that's maybe okay um so data hydrating or hold on we're looking yes that's what we're looking for so data hydrating signal okay so now we know whether we're hydrating and if we're hydrating um let's see yeah and it is hydrating will never change so we can stick it in a dependency array no problem so if we're hydrating or here we can say if we're not hydrating then we return and now this is we're not going to get the warning because this is not a use effect thing but we'll put it in there for completeness um so he's asking why i don't use font ligatures because i think they look kind of funny and and other people do too and i don't i don't really mind them too much but yeah some people freak out about them so i don't i don't care that much does remix have a root at all could you target that yeah i could so we do have a root um we render it we render the entire thing and so i could target like something in here um but that's a bit of indirection i kind of like that um i have this uh right here and i'm like what is this oh it's that okay yeah now i sort of get what's going on um so yeah there there probably is another way that we could do this um we could even make like a global variable that we mutate um that that could work as well um yeah but i i'm kind of happy with this okay cool so now if we're hydrating um or if we're not hydrating then we we don't do anything uh we don't care yep okay cool so this should work now if i go to advanced then i'm restored into the scroll position but if i go over here and then i quick advance we should be at zero boom that's what i'm talking about so there you go that's another piece for the advanced stuff but we're gonna go to simple and simple is much simpler um simple doesn't need all this nonsense um and so we're gonna get rid of a bunch of it um we yeah let's see we do still need um uh to request let's see i think we'll probably use use fetcher for this yep we're going to use use venture to get all the data as we go rather than this start and limit nonsense in these search params um transition may still be useful maybe but mounted stuff that we're not gonna need that uh before unload ssr layout effect not gonna need that um yeah okay so lower boundary upper boundary stuff i think we yeah we're probably still gonna need that so this is like we have this much data and we're showing this much of it most of the time um what what most people do is they just add more data and then as the user scrolls back they just they still have all this um and so we could probably make it all uh fair about a fair bit bit simpler by um by just keeping the data around uh that's what everybody does um here actually you know what let's see what twitter does if we are looking at our memory and we uh oh that's interesting will this show us over time i thought i was going to have to take snapshots and stuff so we're at 83 megabytes we're at 113 we're at 126. okay so they do clean it up oh right yeah of course they do because they're garbage collecting um yeah you you wouldn't be able to do this very reliably if you weren't doing that now that's interesting i'm stuck can't go any okay there we go maybe i was stuck at garbage collection no just kidding that would freeze up everything um huh that's so weird that i'm getting stuck yeah well anyway they have to manage garbage collection you won't have to do this um at least with the advanced thing uh that we're working on so anyway um for our simple one though um we will um will not worry about garbage collection um we'll just keep on adding more stuff to the to the data and then people can use the advanced one if they they also don't want to worry about garbage collection but they don't want it to be a problem either so with that we don't need to worry about the upper and lower boundary all of this stuff we can get rid of that and all of this okay cool so we've got our infinite scroll our index is literally going to be the virtual row index it like this drastically simplifies things if you don't want the much better experience than what we typically experience on the web for infinite scroll okay and we don't need this we're not going to need that or i could just do this um yeah okay and also most people don't server render their infinite scrolls either so we'll show that um not infinite scrolled let's see we are still gonna need a start and uh limit sort of thing on the back end so we say the user scrolled past this point let's go get more um and so here's here's where we left off so start there and get like 200 more um yeah so we're we're still going to keep that um this loader runs for the use loader data [Music] and we can server render that first bit sure why not um yeah we are going to want to start which will be um react you whoa real react react use ref initialized zero and then how did we know in here it's on the re-render yeah right um yeah so when it's the last virtual item yeah in fact i remember looking at his example i'm like man that sure is a lot easier when you you don't have to when you don't care about these other problems um so i think it's on here [Music] i think he was using react query to go get uh to manage pagination stuff maybe not oh no it was um variable i think is what he's talking about um so sorry just reading some youtube comments here is remix viable for slowly integrating into existing project or is it only usable for greenfield um it is definitely possible to use remix for integrating over time i i don't know i'm sure that there are people in the community who are already doing it and so you could probably get some insights from them i was working on um refactoring a remix app or a a next app to remix and found that to be a little tricky but i think that i i was like basically i'm not done until it's all uh done anyway so i wasn't really concerned about migrating over time i'm pretty sure there would be a way to do that um but i'm not sure what that way is because i haven't tried so you can take a look at uh or or ask people in the discord community to see what they say um so e dev a friend and deb for the church that's i'm guessing it's the same church i belong to we all refer to it as the church but uh yeah that's awesome the calendar app with remix that's sweet you're gonna love it yeah that's awesome okay so variable i think this is talking about variable height infinite scroll that's what i was looking for and this is the one that i believe he's using react query for um yeah with axios and whatnot and he's got this fetch more with this use infinite query um so here yeah he calls fetch more when um the last item index when we're one away basically okay so um whoops um we'll come over here let's see here let's let's bring in our fetcher thatcher use thatcher and i can't remember if this takes yeah it doesn't take any arguments we'll have this react use effect that's fetcher.load which will trigger a get request to go get stuff um and where where do we want to load it i think we can load it i think we can do that i don't know we'll try it we'll see what happens when we do that um i don't think that'll work because i need to add a query string on this too okay what is this complaining about yeah so you can't give it any more arguments yeah i don't expect you would because you're making a get request um but i'd i would want to like maybe put headers on i imagine maybe hmm fetcher dot submit if i do submit then i can provide the um value and then the options which involve the method replace huh yeah i should i should probably look at the docs um i've never i have used nope i've never actually used use fetcher before i played around with it a little bit but yeah not done too much with it uh use fetchers for like um well it's for stuff like this making uh a a network request that is not attached to a navigation that's what it's for uh okay got our type we've got our submission we've got our data we've got our form we've got our submit and then load loads data from a route loader um just like you submit except doesn't cost navigation uh just like form doesn't cop navigation you'll get over the dot in jsx don't worry that was ryan okay oh actually i do use a use fetcher this newsletter sign signup form example was be um i'm my use case on my website was the reason newsfetcher was created um yeah so gerardo is asking if uh react query is a good match for remix um you can bring your react query along with remix if you like um uh you're going to find out that when you're done that you're not doing anything with react query that you can't just do with remix by itself and so feel free to you can it's possible but um you're doing extra work that you don't need to do um combining remix and recoil um yeah so you could do that also um recoil solves a very specific problem and i from the beginning i was worried that people were going to use recoil to solve other problems that um that it's not suited for and that you don't need it for so if you have the problem that recoil is specifically built to solve then great bring it along you can totally use it if you however are just using it to manage some global state management you're going to find that you don't need it so okay let's get back to this so you can load some route and there's it doesn't look like there's any way to set headers or anything like that which um would probably be a feature that that could be useful um i imagine but currently no way to do that um for me i think i'm fine um using load to do an actual get i don't want to do a submission so that's what we're going to do and we're going to say um simple and we'll have our um yeah our query string qs um qs equals new url search brands and we're not going to do that we're going to do this so our start is going to be um how do we calculate that um start is hold on a second total items oh can't go over okay that's for something else all data over scan yeah so this is where we're gonna get our needed start yeah okay so this actually we're gonna borrow some of this um or let needed start equal to start why is this okay yeah um and then our upper boundary is the start plus the limit minus the over scan and let's bring in that over scan stuff and our limit yep we got that right there why are you complaining oh it'll fix itself thank you uh okay and our limit uh limit is always gonna be our uh 200 so start plus the limit minus the data over scan why is this complaining oh whoops oh no that's a ref so this needs to be um oh right yeah i need to mutate start hold on um i think we'll just call this yeah start ref it's always nice to be clear about that [Music] okay sweet so our upper boundary as or no we need the lower boundary because we're gonna just keep on adding stuff we're never gonna remove it so we never need to request for stuff in the past um so we want the lower boundary oh no i'm i'm flipped around lower means um uh lower by index upper means upper by index but lower by scroll that's confusing uh okay so we've got our last virtual item um let's get rid of that okay so we've got our last virtual item index if we have now scrolled past the upper boundary which is um where our current start is oh let's that makes more sense to say the current start but the current start is plus the limit so start plus limit that's as far as we went minus the data over scan so we want to have more stuff so if we are if our last virtual item is greater than this position that means we need to go get more and so now our needed start the user scrolling down move the window down so our needed start now is that minus the middle count divided by the data or scan um plus a date or times data over scan so um yeah so basically we're going to take the whole window and move it so that the middle of the window is where they currently are that only matters if they can go backwards and we need to request stuff in the back um for us because this is simpler we can say oh you made it this far i'm going to um i'm going to just request the next uh the rest of the stuff which will be this um yeah this uh start graph current plus the limit boy that's way easier okay cool so with that then um and instead of calling this needed start we'll just call this the new start we can say if the new start is not equal or is equal to the start ref current then we'll return we don't need to do anything um stringify that sucker um and then here we'll have our limit is limit uh i don't know why that's complaining oh right maybe yeah okay cool sweet so this also wants the fetcher which hopefully is memoized they better memoize that uh i expect they have um okay so we'll load that and then response oh hold on a second that returns void hmm oh right because the fetcher itself just has all the stuff on it that we need um so let's see so when the fetcher is done loading then we're going to append its data to um to the data we already have um which we got from the loader so here's what we'll do we're gonna items so items our initial items are going to come from the loader okay so that works and then when the fetcher is done loading of a react use effect fetcher dot um state um yeah so when it goes back to idle hold on a second i think there's a type also and the type can be done so when it goes to done so yeah and every time we fetch it i'll start over and then it'll come back to done that's what we want um so if fetcher type is done then we'll um yeah i mean that's sort of right but not quite so items or yeah previous items previous items i have a feeling we're going to have some some issues here if you scroll really fast then um we may end up canceling the previous loads i'm not sure we'll have to see what um how that works and um yeah yeah we'll see uh okay anyway we're gonna take our previous items fetcher data as any and then items yeah whatever we can worry about that later and then our start ref is that new start yes okay [Music] and this data is going to give me back items and the total items which i don't need for this but that's fine um okay cool so then we come back down here data.items we'll just use items okay let's see what happens i don't think it's gonna work but maybe it will yeah nothing to see here whoa yeah something something was not happy [Music] uh yeah okay yeah okay so as we're scrolling this is re-rendering like a gajillion times um here let's fix that yellow underline um i bet you're done [Music] adventure is dead [Music] what else are you complaining about oh it wants the new start and the fetcher items oh gee whiz uh yeah i guess in fact fetcher data so if the fetcher data ever changes then the other thing that this wants then is just the new start um yeah okay well [Music] so this is re-rendering and it's calling that fetcher load a million times is that what's going on why is it calling it over and over again let's see new start and fetcher oh maybe fetcher is not memoized that could be um that would be so sad and funny at the same time fetcher use fetcher it should be come on it's gotta be um adventure with components yeah it's memoized uh but maybe there's something else in here that's not yeah that's these are all the trick to get something that like stays consistent forever so those are all fine um so it's just this fetcher that's coming from this transition manager uh that's based on a key so i'm sure that that is also stable um so i'm not sure why um why is this complaining oh right yeah because it wants the new start um yeah i guess you start um yeah i feel a little uncomfortable i feel like we may end up putting the same items in twice in a row or something there's probably a better way to do what i'm i'm doing we'll figure it out um okay so why is it calling fetcher load a bajillion times [Music] the new start is equal to start ref current oh right because yeah that's why because we don't actually update the start ref current until the request comes back which is too late so we update it here and now we don't have to do this and now that resolves that problem okay let's try that so now we come down here and there it makes a request and all the items there we keep going and boom okay sweet now my question is what if we are on a slow network and we scroll really fast yep there we go we're canceling these requests which um yeah i can kind of see [Music] that makes a little bit of sense um yeah see and now we're off because we cancelled the request for some of those um so the solution then is um because like so what's going on here is we scrolled and we didn't wait for things to finish loading we just kept going and so clearly we don't care about that data we scrolled past it and so um canceling it is correct we don't need it let's just cancel it um that's that is correct that's what we're looking for um the problem is that we're just appending things so what we really should be doing is um inserting things at the particular index where they should be the problem is that we have no mechanism for when the user scrolling back to say oh my gosh it's 5 30. um seven i have a piano recital for my kids you know like not too long so i've gotta go um that's not what we were saying um oh my goodness time flies by um so yeah we've got um uh we were canceling this because we scrolled back uh scrolled past it but if i scroll back then i need to be able to say hey is that uh do i have that data uh do i have that section of data if i don't then i need to go get it so there will be a simple mechanism for doing that um to just check not only um is my new has my start changed but also um is that um is the data that is at that position um already do i already have it starting to feel like i should come back to this advanced keep some of this logic as we have it so that we can do scrolling backward and forward um and and then just remove uh less so we'll keep most of this stuff but we'll remove like the query string and restoring scroll position and that sort of thing um so yeah that this will still be required with the simple version okay anyway we're going to do this tomorrow um so yeah how would you scroll past something that did not load so um because we're using virtualization um we say hey this is how long our thing is um and so we we make it so that it looks like that's how big it is that's what windowing is is it you just make it look like it's there even though it's not there and um yeah so that's that's how that works it's magic um and it's fake but it is the only way you can get like good performance on some user experiences oh and ryan comes in here what's up brian um i don't know if fetcher is stable your fetcher changes after it loads um i don't know when you said that four minutes ago so i think we came to the same conclusion um oh oh he was talking about memoization your fetcher changes after it loads oh that's interesting so this uh um transition manager fetcher key uh it sounds like what you're saying is that change of that should not change but maybe the transition manager get fetcher will give you a new fetcher every time or something in any case uh ryan if you have ideas on what well no it seems to be working i don't know i don't know it it looks like it's stable but maybe it's not he says i don't know i think it is anyway um yeah i think i know the the best solution forward here so we'll work on that some more tomorrow um thanks everybody for hanging out this is fun and i hope you have a marvelous evening i'm gonna go to my kids piano recital now peace [Music]
Info
Channel: Kent C. Dodds
Views: 1,748
Rating: undefined out of 5
Keywords:
Id: P03VwrKO8P4
Channel Id: undefined
Length: 88min 43sec (5323 seconds)
Published: Tue Dec 14 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.