Building React-Select | Jed Watson

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone this is really cool I'm so stoked to be here five years since I came to my first react conf and this is my first time seeing it from this side honestly I could not be more excited to share this story with you so thanks for the intro Devin I'm Jed you might know me from the internet as Jed Watson and I work for I actually co-founded a consultancy in Sydney called think mill I think mill we make software but this story isn't about that this story is about something that I made called react select now it was actually almost five years ago to the day that I published the first version of react select NPM I had no idea what I was in for I started myself that was really cute that's that one star there and over the next year I actually it matured I had a lot of stuff to it I got 1.0 beat her out that's okay react was still on a zero dot release at this point so you know it was very cool to be in beta started picking up some stars another year RC so what comes after beta the artsy stars went up that was pretty crazy and then another year after that one point I was released and everything's kind of tracking along nicely but you'll hear more about that in a minute I want to give you the timeline of the whole project so a year later we actually released version two which was a huge rate right and this is where I've started tracking downloads and as that today yeah this good just got big wow that's a scary amount of downloads per week honestly also this is a really long time this is five years of my life in like one component I've changed a lot in the last five years it's also changed a lot in the last five years anyway this is a story that I wanted to come here and tell you today so it's a story about a select component and my experience is an open-source maintainer and how that worked out so there was a really great talk earlier today and I this one-line stuck with me I created a terrible first draft you know like yeah I sure did and then another and then another but it is kind of masterpiece and just to put that in context like I don't know how this happened react Dom gets five and a half million downloads a week that makes sense to me classname still gets a lot Redux and react router I'm like yeah they're huge but reacts left actually gets 30% of the downloads of react Dom which means that for every person or every like three people using react on the web or I guess if your county buddy downloads someone's using react select why it's crazy right it's just a select component so it's actually got quite a lot of features I set up from the start to build a whole lot of stuff because I needed them for a couple of projects I was working on there are things like search as you type single and multi select focus management when you're layering positioning being able to pull in menu items asynchronously from an API also a huge focus on accessibility and touch support keyboard and being able to create new items if they didn't exist and it wasn't just about the features I had some design goals for the project as well that I think might have helped it in the early days so the design goals that I had were that it had to be powerful I wanted to make a proper declarative react API for it I didn't want it to be too opinionated I had this idea like you should just be able to use it in all these different scenarios and just because you're using it like if people are putting this in their apps then they need to be able to own the data they need to own the way it's working they need to be able to control it it should also perform really well and finally like despite the power and the flexibility I wanted to just work like out of the box right you install this thing from NPM you put it on the page and it just works big goal so I got to it and I've got to say react made it really really hard there's all this crazy imperative logic that you need to abstract like focus management you click on the control and the focus needs to move to an input but the controls already focused like it's it really it bent my head for about a week actually the first time debouncing updates and but I sort of it was like a deep dive into the lifecycle of react and eventually react was right and I learned and it started working I got it to work and it was like this Wow I know how to do this now it's amazing so that was really quite a cool experience building for the first time I used for the nostalgic amongst you in the audience react Oh point twelve underscore class names less gulp and browserify this was my tool train of choice just to age myself but I put on the internet and it was a blast by the time I was done I had about 50 props all this internal state intricate logic I was really proud of it it worked and I learned about the first phase of open source which is joy excitement and stars it's really exciting you put something out that people like it they start using it you get happy you feel like this also side effect of publishing stuff on open sources of people open issues in PR so you actually get to learn a lot you get to integrate a lot of new knowledge into your project and I did that I also made some really good friends along the way so early contributors people like Brian reached out and started helping me and it's been really good quite a few of the people who works with me on this project and friends like some of them are in the room today but honestly things got a bit out of hand and all that intricate logic that I mentioned yeah that led to a lot of core complexity and you know this is kind of understandable for a first draft oh wow that's too many slides alright so now react is meant to be really good at this as things become complex you can break them down into components and compose them back together again axé really good at helping you with this in fact there's a whole page about it called think interact now this is my favorite page on the react ox no this is like if you could read one page on those Docs so down it would be this one for me and it's got this great diagram of how to think about breaking up a UI into smaller components but what if you can't actually break down a component any further all right the challenge with a select is that they're really complex and sophisticated but you can't actually break them down into any smaller primitive the way they manage options and values they sort of behave like a single input and the way they manage focus and accessibility like it's all kind of got to be tangled together they need to be controlled by a single brain and you can probably see where I'm going with this there's every new use case required more complexity to be added into the core component and the thing is like everyone who has a different use case for a component like this only really needs to customize about 5% but every person needs to customize a different 5% so your surface area of like what can be customized becomes a significant amount of the component and because of that issues and pr's mounted edge cases coming in conflicted with other edge cases and also what happens this is my favorite slide this is me my wife and our daughter thank you this is a really happy slide for me honestly like if I could get away with it the rest of my talk would just be photos of my daughter right because like that's all I want to think about and that is what happened to react select this is kind of where the wheels fell off right between the complexity of maintaining it and trying to integrate all these different use cases and fix bugs and just having less time oh you know I had a life and a job and a new child and reacts like it was actually none of those and it suffered for it and so I learned about the second phase of open source which is maintaining the anxiety and loss of sleep having hundreds of open issues and PRS and a lot of community frustration because on the other side of each of those issues and Piazza's a human who's put their time into either using your software or contributing to it and you're not talking to them you're just ignoring them and that feels terrible it really does but I had a lot of time to kind of reflect on this and learn from what went wrong and the way that I'd set up the project it was hard for anyone else to step up and understand and maintain the complexity that existed and also just like the way I architected the component I spent a lot of time thinking about the way I'd Architecture the component and I started realizing that actually any way out is through I have to architect myself out of this mess and so I really wanted to do that and luckily about this time think mills started working with Atlassian on Atlas kit which is their reactor design system and if you've ever used Atlassian software like JIRA you'll know it's got a lot of selects like your is basically a glorified form interface right full of selects all it does they have components for assigning users and filtering issues and changing statuses and selecting options and inserting emojis and since I'm an async and some are fixed and like everything everything you can think of everything that moderately looks like a select atlas get needed to build so I was like cool how are we gonna do this and I had to look at the way that they done the selecting that was kid by the time I sort of got involved and started working with them and they had to there was a single select and a multi select that had stateless and stateful variants on the problem with this was I looked at that and I was like wow these are just as complicated as mine is and they've got all these features but they've actually got more yet to implement than they already have implemented they're already this complex like this doesn't scale not at all but also I looked at the list of things to be done and react selected already implemented most of them so I had some prior art to draw on and we started thinking wouldn't it be cool if we could figure out how to create a new select built on the maturity of a two-and-a-half-year-old open source project that actually could scale and do everything that you needed to do or in other words we started thinking not so much about how to build a component as how to build a framework inside a component so that version to rewrite that I mentioned that came in about halfway through the lifetime the project this was it and what I did instead of looking at other components another react code to figure out how to address this I looked at other significantly successful open source projects I took inspiration from things like AAS lint or Babel which set themselves up as frameworks and then offload all the complexity of the different use cases into user land you've got all of these plugins that just hook into the core API is and I thought how could you apply that principle to a component because those projects they're sustainable they get maintained that works really well for them can I do this how do we do that in a react component so spend some time thinking about things that make up a component and got down to three as state and there's functionality and there's the user interface which is the view and the styles that result from that how do we change that well we got one thing props that's how tool how do we use reacts props API to control these things and make them flexible let's start by having a look at state and functionality what we can do is we can break these down into smaller independent parts and use this props API to allow them to be controlled by other components let's have a look at things you can do with props fundamentally I think there are kind of four major categories there are state or switches there are events or callbacks that get fired by the component when that state should be updated you can do extensions or functionality by passing functions into props and of course there are children or render functions so using these let's see how we can simplify the component starting with state this time react select has four discrete buckets of state this is much more obvious these days with hooks but when I really looked at what was in my bucket of state it was these four things you've got the options for the menu the current value of the component the current value of the input inside the component and finally whether or not the menu is open so we kind of broke those down into four distinct things and made them controlled now to that second type of prop because these things need to change we need some events let's add them in alright now we're expecting these states be provided and just calling out to the event when they should change and this simplified the core of the component considerably because no longer did we have this branching logic for controlled or uncontrolled within the component also now a component can be smart or dumb in you know different ways you can mix and match this stuff together this is great but I'm sure you can see the problem if react select isn't managing the state that means the user has to now and that broke the design goal of it just works enter the higher-order component pattern so I'm sure you've all seen this or use hired components at this point but this was actually a breakthrough in how to extrapolate flex sort of complexity out of the core component into other components I'll show you a simple example of how this works just to manage that value and unchanged prop so breaking this down we have a new component that accepts value and unchanged we then track some internal state we determine whether we want to be paying attention to the if it's provided or the internal state value we create our own on change which is like a transparent kind of pass-through method which will update the internal state but also call out to the prop if it was provided and then we put those onto the components spreading the rest the props through so we have this transparent state controller now but we can wrap around our select component and export it from the package and get back to it just works it's as simple as this we input the select in the menu state and we wrap it and we're done that's a pretty simple thing to do let me show you how it gets more interesting that asynchronous version originally was like a lot of the complexity of the core component and we use the same pattern to do this as well so get options returns a promise we have some state this time we're handling the on input change and we're spreading norland for select so this pattern is really powerful and in terms of exporting it it looks like this that async component can be simple because it knows that it's going to get wrapped in something that's going to manage its state for it now we're good now let's look at another third category that things you can control with props which are extensions and functionality so we consolidated a lot of learnings from version one and really focused on how to use props in a way that made the component more powerful and consistent remove that goal under pinyin ated and like respect the the sort of user the sovereignty of the data that people are passing you through I'll show you what that means you have a select component and it gets passed in options it passes the same value to the unchanged untouched select doesn't actually need to know anything about that because you can customize how the options are filtered the way that they're selected right we have same defaults but we kind of allow the user to change as much or as little as I need to about that I'll show you an example if I've got these options myself and Brian and I wanted to use instead of a label a first name and a last name property all I need to do is add a gate option label method to that to concatenate them together and we're done oh let's look at filtering react select has quite a powerful filtering library built into it you can create variations on that and pass it in but to that to work with this new example I just need to take the candidate in the input and like write my own function and I'm done so I've replaced as much of that API surface area as I needed to but nothing that I didn't now the final piece of the puzzle if we're really empowering the user is telling more information about how stuff's changing declarative is quite limiting in the sense that we can't say we can just say this is how it is but we also need to provide information on why so going back and having a look at events again in the context of supporting extensions originally we just had this unchanged which would send you a value we added matter into that to say why it changed and that's also really powerful for extension authors because you now know all this value was changed because user added an option or removed an option or cleared the control all that sort of thing so that's the state and functionality out of the way I'll just remove those values from our select and let's have a look at things that make up a component again circling back to the start so the last piece is user interface now this is actually this is my this is the thing that I'm most excited about so one of the things I've always loved about react is this pitch view is a function of state this is really simple to get a head around but I'm gonna extend on it a little bit and say that it's not just the view but also the styles other function of state because those two things together make up what you're seeing on the screen and so shout out to a motion and CSS and J's for really making this a reality in react slick this is incredibly powerful if you're trying to build something that's extensible so remember how I said a select is a really scary big component it's still made up of identifiable UI components and they look like this you've got the container the value label space for a loading indicator separator a drop-down a menu a bunch of them so we came up with an overrides pattern that lets you customize all of these and what you can do is you can specify your own component or your own style function to apply to each of these different components that the Select wants to render and they're both the function and the view component are provided the same state by the Select itself this is really powerful so we'll take this example myself and Brian again and let's say that we wanted to take that value and link out from that value component to our Twitter we can do that we create a custom value component we render that link we pass the value component into the Select and hey presto went out links and people can do this without changing the core anymore let's get a little bit crazy let's use a styling API and add a color in to each of us so now we can create a value Styles function again it takes the same State which for a value is the one that it's representing we can change the background color pass it through to react select and now we can be themed and this sort of thing was never possible in version one this is actually a huge advance but we can put it all together and do even more powerful things I had this crazy idea I was like how far can i really take this what if I do something just ridiculous what if I try and create a date picker because that's the other category of really complex component in react and what if I accidentally solve that as well I did it works it's so crazy it works this is the default set of options that are provided to the component I hooked up the on input change to a natural date language parser to pick a date so when you start typing in next Monday it actually picks next Monday for you or if you type in something like the 25th of August it will go straight to the next 25th of August and this is just like in userland this is an example on the react select website in about a hundred lines what's going on here is we have we're listening to that on input change just like with an async select but then we're running that through our natural language parse of we're picking the date we think it is and we're generating dynamic options rather than loading them from server we're using a group to create this calendar type thing and then we using our custom styling API to make any of the dates inside of a group render like a calendar and we're indenting the first one by the number of days and that's all just using the api's that I've shown you yeah it's cool [Applause] so like this happened and I knew I was onto something because for very little effort we got all of the same accessibility keyboard touch support of our course select component like for free out of the box it's maybe not the best date picker in the world but it's actually a really good one and what I realized at the end of all this was coming back to thinking and react components aren't just for UI there for State and functionality as well and it turns out we actually can break down a select into smaller components and with this new customization API most of these use cases didn't require changes to core anymore and with that I found the third phase of open source which is you know mostly sustainable it's better it's not it's not perfect but man it's so much better so this made a lot of difference anyway some takeaways for you the things that I learned through this journey so some for react architecture reacts composition model for me has always been its secret weapon this is why I got so kind of attracted to using it in the first place like being able to turn things into components and compose them in a hierarchy like that's it everything else is just making that work the reason why is it allows you to let complexity in and then break things down compose them back together again and repaid and the secrets are doing that successfully is paying attention to which component owns the state and just designing good props with that in mind all of the bad things I've seen happen in react applications is when people haven't thought about which components should own the state or how that should be able to be controlled it's it's it's it's I want to say it's that simple but it's not it's actually really hard but it's it kind of ends up being that simple once you get your head around it for any of those of you who work on design systems in the audience this actually ended up being really influential on Atlas KITT and other design systems that we build at think mill the whole pattern led to multiple different components composed on top of lower-level primitive components and when I say primitive I don't really mean like simple obviously the core select is not simple but that composition pattern actually you think about the ones you finally export as the artifacts your design system everything under that is part of the framework of your design system and that helps them scale and be a lot more sustainable a good way to think about how much to lean in on this that I've been sort of thinking about lately is this where is the complexity you can think of a bit of a spectrum of complexity from is the complexity in the styles is that all there like a button there's 50 different ways of rendering it but it doesn't have to do much or is it like a select where really it's halfway in the middle and then you're probably going to get a real benefit out of thinking about that component as a framework or even something like a tooltip where most of the complexity is just in positioning and rendering and timing and debouncing and things like that also for design systems I just want to bring this slide back up again because I can't emphasize how much of a game changer this was moving away from static style sheets where we had to breed it home in the state to being able to use state dynamically for the I know there's a lot of trade-offs and cost sort of benefit that you can look into in terms of how you're going to do CSS nsj and or versus static also choose your own library but this was a real game changer for this kind of component and final set of takeaways is for anyone involved in open source as hopefully this helps explain composition is king people will find use cases that you have never imagined that's the fun but some of the fun but how do you design an API that makes that possible once you've got that API automate everything or even beforehand automate everything this lets you maximize the time spent actually considering those issues and PRS and not the manual process we came up with a whole lot of Forex elect including a lot that we built ourselves to make it sustainable we have prettier in Iceland for code styles we have this great tool I want to give a shout out so called change sets which manages all of the change log generation and release process we have automated website deployment to net will fire branch prove your deploy so when a PR comes in I can actually test it and see it and play with it while I'm looking at the PR without cloning that branch locally we all the examples have a button that will let you launch them in code sandbox automatically which is great for getting people to submit issues with reproduction cases we generate although our documentation automatically from our types there was a talk yesterday that demonstrated a similar thing but we did that as well and it's I would never have been able to document the the surface area of this component without a tool like that and keep it in sync and finally tools like Cypress for automated testing are also invaluable and the last one for any maintainer is to empower other maintainer x' getting other people who helped me with this has been the best thing ever I want to give shoutouts to Joss moccasin day brother stone Brian Vaughn Charles Lee Mitchell Hamilton and the atlas kid team for helping me with this because without them I would not have been able to do it find anyone friends family pets it's in maintain as just your best friends in open source as a little bonus for anyone who is using open source now the other side of this whole puzzle let me just share a couple of things with you from my perspective that I've learned over the years the first one is stuff like this is really not actually as helpful as you think it is no let's not do this instead this tells me nothing all right I've got this super complex component and I'm trying to figure out how to incorporate some idea that you've got that you think you need into my abstract problem-solving brain I don't want to know that you need something the way it's written all the way you think you need it I just need to know what you're trying to do because then maybe I'll understand that you need it or maybe I'll realize that you need something else so I'm trying to do X and this would help me because Y is really the information that is makes it so much easier to maintain these projects or even better sometimes I get this one and I love it is there any way I can help all right yeah thank you if someone's not responding to you on github it doesn't mean they're not listening it might just mean that they're actually really struggling to find the time to answer it in the format that it's been posed that's a real thing this was asked to me on Twitter just last week is it okay for someone new contributing to an open-source project to a comment or review a PR and yeah absolutely that's actually really helpful as long as it doesn't look like this this is me I did this it just looks good and submit review Mitchell your star thank you yeah same thing right it's not actually helping me as a maintainer understand the code review that you've done tell me what edge cases you found tell me why the change is safe help me understand it without spending the time syncing to the code myself as deeply without any context that's a super useful thing as well and finally just be nice to each other I've had so many people get angry with me on github that I've never met I've had people treat me like it's really weird I'm nice try and be nice just be nice to each other and as an open-source maintainer I've had issues come up that like just deeply upset me and instead of spending the next two hours that evening answering issues and and reviewing PRS I'm just kind of fuming inside I'm upset and I can't get myself back out of that headspace and I go to bed upset and like you know what it didn't do anyone any good I didn't ship any code sorry that was a bit of a rant but like you know so important let's be nice to each other anyway are we done nah of course not there's heaps left to do on reacts look from here working on a hook story right to prepare for concurrent mode I'm really interested to see how these composition patterns that I showed you evolve once we get two hooks and concurrency I think they'll change a little bit I'm not sure how much I think they'll simplify the logic a bit more but it's gonna be really interesting to see how that evolves I'm hoping that being able to bring those benefits that the react teams been talking about with hooks to the project will also help make it friendlier for other contributors to come in because it does make the chunks of logic and code it's dealing with clearer so you're welcome to contribute if you want to help if anyone wants to shout out and help me with this come and have a chat or reach me on Twitter that'd be great and final shout out we are actually working on a design system framework at think mill that's turn to take these principles to a broader set of UI components and if anyone's working in a similar space I'd love to talk to you about that as well afterwards get in touch with me and that's it from me thank you [Applause]
Info
Channel: React Conf
Views: 12,666
Rating: undefined out of 5
Keywords:
Id: yS0jUnmBujE
Channel Id: undefined
Length: 31min 6sec (1866 seconds)
Published: Wed Oct 30 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.