Jenn Creighton chats with Kent about how she keeps her React codebase clean.
Jenn has been working with React since 0.13. She has a background in creative writing, and it melded well with React.
One of her big early mistakes with React was focusing too hard on making components reusable. When you try to make your component one-hundred percent reusable, you end up with a massive stack of props. In our effort to make things reusable, we end up making it harder for ourselves and others.
Sometimes it even makes sense to duplicate the component, change its name, and add your changes to it instead of adding more props to the existing component. Too many props on your component not only makes it hard to refactor but also difficult to even use.
One of Jenn's rules for her codebase is that new engineers should be able to come in and get up to speed quickly. It is an overall rule that has to do with keeping the codebase consistent. Jenn puts rules in place like, "We consistently use this state management library." So if a person comes in, they aren't finding multiple ways of doing the same thing.
Document it before you write your next component!
Kent C. Dodds: Hello friends, this is your friend Kent C. Dodds, and I'm joined by my friend Jenn Creighton. Say hi Jenn.
Jenn Creighton: Hi.
Kent C. Dodds: So Jenn is a wonderful person. We were just reminiscing over how we got acquainted, and it was last year for ReactRally 2018. I was preparing to speak about React patterns, and I wanted to talk about the props explosion that happens when you have this "reusable" component. And I think I asked "What's one component that you know that has the most amount of props you've ever seen?" And I found one that was over a hundred props. It was nuts. But Jenn responded with the best tweet ever, that I actually included in my talks, you said, "I call that apropcolypse." That was so good. I loved that. That was so great. So that was my first introduction to the wonderfulness that is Jenn. Jenn, you do a lot more than just tweet really great puns on Twitter. Could you give us a little intro to yourself, please?
Jenn Creighton: I mean, that really was my best pun, so I don't tweet that many puns. I try. But yeah, so I am a front end architect at a company called The Wing. We build women-first coworking spaces and I joined about four months ago, so I'm taking on a new role in front-end architecture. And before that I was working as a senior front-end engineer at ClassPass.
Kent C. Dodds: Interesting.
Jenn Creighton: And I do a lot of talks. A lot of traveling. Yeah, it's my hobby.
Kent C. Dodds: So it's a hobby, not specifically for work?
Jenn Creighton: Exactly. Yeah. I mean, work appreciates that I do it. It's definitely a plus for them, but it's not part of my job. I just really enjoy public speaking and teaching.
Kent C. Dodds: Wonderful. And I'm looking forward to React Conf where I'll get to experience that firsthand, seeing you give that give a talk there. I'm not going to spoil it for people, but I am super excited about the talk that you're going to be giving. I believe we should hopefully have this published before that time so people can get ready for that great talk. I hope I'm not overselling it and making you feel uncomfortable, but I heard the topic and it sounds great. So, great. Jenn, how long have you been using React?
Jenn Creighton: I would say about four or five years now, I think, five.
Kent C. Dodds: Wow. That's a long time. That's definitely way more than half the people... Okay, if we take all of React's community, all the people using React, you've been using it for longer than way more than half the community, I'm sure. So you've been around since pre-major version days, like 014, probably 013, right?
Jenn Creighton: Yeah, 013. That's around when we started to use it at a company. I was actually the person begging to please use it because we were using Angular1 and that was my big impetus.
Kent C. Dodds: Yeah. I can relate to the desire to switch from Angular1, as great as it was. Don't get me wrong, I liked Angular1 better than Backbone, for goodness’ sake. But, yeah, I was pretty happy to move on to React, myself. So five years of React, I'm sure you've experienced a lot of things. One thing that I have come to realize the longer that I've been working in software is that the longer you work in it you develop more experience, which seems obvious but you are exposed to more problems and therefore you gain more experience.
So your experiences of five years working with React have probably taught you a lot. What are some of the lessons that you've learned in the process of building React applications, architecting applications and some of the mistakes that you've made? What would you say are some of the biggest lessons that you've learned in using React for that time?
Jenn Creighton: In the early days when I was just starting out with React, truthfully I had no clue what I was doing. Angular1 was very different and before that I had worked with a proprietary framework at another startup that wasn't from a big name. Coming to React was really a lovely feeling, actually, because it really aligned with how I was thinking about components in this declarative sort of state. And the talk I'm going to give at React Conf actually really dives into this, where that comes from and my background with creative writing and why that melds so well with React.
I think some of my earliest mistakes were not leaning into that, not thinking about the structure of the components as declaratively and really still focusing on "What do I need to do in this individual component?" and then not being able to see the forest for the trees. You're just in the trees and you have no clue and you're adding in props. You're like, "I need this one, too, and this one." And once you get out of the component and start to use it you're like, "Oh, this is not good. This does not feel good."
That was some of the early, early mistakes as well as really over focusing on reuse. That was another huge, huge pitfall early on just thinking like, "I need to make every single part of this super reusable, just in case. Who knows?" I mean, you and I have seen what that leads to. It's the apropcolypse. Never going to let that pun die. But that's how it starts, basically. Someone's like, "This has to be as reusable as possible. Just add more props to it and we can reuse it. Isn't that great?" No. That ends up being usually a complicated nest of code that you have to unravel at some point.
Kent C. Dodds: Yeah, precisely. I think we get so excited, especially moving from a situation where our code wasn't very reasonable to a situation where our code can be super reusable, we get really excited about the possibilities. And, as programmers, I think we just naturally have this idea that like, "Oh man, I can do all kinds of this magic stuff and we've got this abstraction that it's a black box and I can do all kinds of nutso stuff in here." But it's funny, in our efforts to make things really reusable and simple, we actually make things harder from not only the maintain standpoint where we're like, "No, I'm fine maintaining something hard as long as it makes it easy for everybody else," but it not only makes it harder for ourselves but also makes it harder for everybody else.
So how do you avoid that kind of a problem? What do you do to solve both problems? I mean, I'm okay with a little bit of a complexity that I have to maintain as long as it's easy for everybody else. But is there a way that I can make it easy for everybody else and easy for me as a maintainer?
Jenn Creighton: Yeah. And so this question of "How do I make it easy for somebody else?" is where a lot of the work that I do when I'm starting to build out a component really comes into play. So some of the early stuff that I do, like very early in the process when I'm like, "Okay, I'm breaking down a page." And as you said, we are very much trained as engineers to look for the reusable stuff. And so very early on we're already looking at design and we're like, "Look, this thing is reused so I can make this into a reusable component." And that's fine in small cases, but occasionally you don't realize that you're about to make a reusable component that's handling three to five-plus states. And that starts to get really unwieldy and no one's going to use that, in the end, because they're going to have to supply so many props to it, it becomes actually not easy to use.
So one of the things I do at the beginning stages, I actually write down the API for the component. And this is ensuring, from the outside when you start using the component, that you're actually thinking about the end user, which is you as an engineer and your fellow engineers. And some of the points of it are like, "How much insight do I want to give them to how this component works internally?" Maybe I want them to know, maybe I don't, and that's a big consideration. How easy do I want the API to be? How many props? Can I limit the number of props so that they're not frustrated with this? Can I make these really clear? That's some of the really early stuff.
Kent C. Dodds: And making a configuration objects, like a prop that is just a configuration is just more props. You're not lying to anybody. That does not solve the problem.
Jenn Creighton: No, it doesn't.
Kent C. Dodds: One prop that's an object or configuration. That's just a bunch of props.
Jenn Creighton: No, I've started to do this thing at work where if I see a props-type dot object somewhere, I'm going to ask you to flatten in and out and we're going to see how many props it actually adds. Because that's an anti-pattern to me. You can't do that. It really is just like you're just lengthening out this prop list. And I think people just think, "Oh, but this is how React is supposed to be. We are supposed to get reusable components out of it. It's meant to accept props. Like why would we need to think about these things?" And my response is like, "Well, your whole app is essentially like one component that you're feeding in all the props you could ever want. Do you just want to create one component that could be your entire application?" That's the reason why we break it out.
Kent C. Dodds: Yeah. And actually I've got a blog post about that where you could build your entire app as a single component, but there are good reasons to break it up. And, you know what, code duplication is not a bad thing by itself.
Jenn Creighton: It's not.
Kent C. Dodds: It's totally acceptable. And sometimes it makes things simpler.
Jenn Creighton: It does. Sometimes it's fine to duplicate a component, add a change to it and rename it this thing with whatever. I do that a lot. We have event listings on our site right now. Sometimes the event is going to be wait-listed. And so it changes it how it looks a little bit. I'd rather just create a wait-listed event component and pull up the logic to decide if it's wait-listed or not somewhere else. I don't want to keep it encapsulated in the event component. That's not its job.
Kent C. Dodds: Yeah. That's an interesting point to bring up. So there seem to be two schools of thought around this idea where you have some people who say, "Let's break out these components, break them down into their smallest pieces. Any component that's longer than three or four lines is probably an anti-pattern or something." And then you have other people on the other side of the spectrum who just make these giant render methods of all of this JSX in there and it's managing a bunch of state and has several concerns all lumped into one big component. Where do you see yourself based on your experience, what has worked the best for you? And can you elaborate a little bit on how that's worked for you?
Jenn Creighton: I think for me mostly it's been separation of concerns. I don't lean so much on the size of the component. What I'm more concerned about is what does this component need to know? What do other components need to know about this one? Does my whole application need to... Is going to be affected by something that's done in this component. So thinking about those sorts of rules and then starting to break it down. And obviously I think one of the big, big, early mistakes that I made was putting a lot of business logic in my components. So I'm just a proponent of the more you lift that up and out, your components become way cleaner. So that's a big deal for me. But I don't lean, I would guess, heavily on the "Everything should be a certain size." And I definitely do not go towards the rat nest, everything-in-there components. I tend to be a hybrid approach as much as possible.
Kent C. Dodds: Yeah. Yeah. So it's not like a quantitative figure that you can put an ESLint rule on this and say, "If this, then it's bad," but you may make it more intentional, I guess.
Jenn Creighton: Yeah. It's similar to how I feel about dry and reuse. I think that dry is, when you go hard at that rule, you probably end up making poor choices. And also when you leave it out completely, you probably end up making poor choices. It's really about, over time, getting experiences with the trade offs of what's going to happen if you duplicate something or not. Yes, it's annoying if I need to change the events component and the wait-listed events component, but they both need that change now. But it's two changes. It's not 20. In that case you might want to start thinking of an extra layer of abstraction on top that's going to prevent that.
Kent C. Dodds: But it all comes down to being intentional-
Jenn Creighton: Yes.
Kent C. Dodds: ... about the design of your components. Yeah, that's very good. So when we're being intentional about design, we have to know what our intent is. Is that something that just comes from experience and therefore you just have to use it for five years before you gain that intuition? Or are there things that people can do? You mentioned documenting the component first, which I think is a great practice. Or are there other things that people can do to kind of accelerate or increase the impact of the time and experience that they have so that they can avoid some of these pitfalls and be more intentional about building their components and abstractions?
Jenn Creighton: There are a few things I've done to really ramp up more quickly on this. One is having a method for breaking down components, which includes now I remove a lot of the content in the component so I can see them without the content, because the content can be really distracting sometimes when you're trying to figure out separation of concerns for things. The other thing I do-
Kent C. Dodds: By content you mean like the JSX that you're rendering? Is that what you mean?
Jenn Creighton: If I'm looking at a list of events, I'll actually remove the text from inside of each event so that I can sort of see a little bit more about "Well, okay, taking all the content out, taking all the text out, what is this component actually concerned about and what does it actually need to do?" And that really narrows it down when I'm building out the component API. That's helped tremendously getting better at this.
And the other thing I do is I read a lot of code from open source libraries. That's how I usually start to work with new patterns. The render props pattern. I actually learned from Downshift, reading through Downshift. So I do a lot of looking at... We pull in a lot of third party React libraries, date pickers and selects and tool tips and things. And it's really beneficial to find two or three of them and look through their source code and figure out what they did differently from each other and figure out the trade offs of those things, the pros and the cons. That really helps you see why you would want to maybe introduce a pattern into your own code base or why you might want to stay away from it in certain cases. Those types of things.
Kent C. Dodds: Yeah, that makes a lot of sense, looking at other people's code, especially if what you're trying to do is build an abstraction that works. Looking at other abstractions that have been proven to work and see how they went about doing that and the patterns that they implemented and how those patterns were implemented. That makes a lot of sense. I, myself, have learned just a huge amount from open source libraries and also contributing to open source libraries because then you get these pros reviewing your pull requests and things and they can give you some feedback there. So that makes a lot of sense to me.
Jenn Creighton: Yeah, and also thinking about how you would improve it. A lot of this was kicked off by me using third-party libraries and being like, "This is not feeling good. Why doesn't this feel good? How could I make this feel good?"
Jenn Creighton: Oh, I definitely remember looking at some of the source code for jQuery and having it just blow my mind. Like, "Wow." And now I do actually the same thing with the React source code. I love going into the React source code and finding out what is so different about building out the framework than it is like using it. So it's tremendously interesting.
Kent C. Dodds: Absolutely. And I think at some point you have to have that revelation that the dependencies that you're using are written in the same language that you're using those dependencies with. Right?
Jenn Creighton: Yeah.
Jenn Creighton: Definitely not, definitely not. About no understanding right away.
Kent C. Dodds: Yeah. But stepping through with a debugger or something so you can follow the code path. That's a huge amount of benefit there.
Jenn Creighton: Yeah, it really is. And you know what? I think it's fun. That's how I enjoy spending my evening is by the glow of my computer, debugging React source code. It's fun.
Kent C. Dodds: Yeah, yeah. And if you need something warm on your legs, on your laptop, you just spin up some crazy process, process some video and now you're snuggling with your laptop and it's great.
Jenn Creighton: Oh, I never feel like my laptop is not a million degrees.
Kent C. Dodds: Yeah. Thank you, Tim Cook, for your fun machines. So, as far as React component architecture is concerned, what are some of the things that you found to be... So, we've talked about reusable components and maybe not always reuse things, but when we're talking about large-scale React applications, what are some things that you've found to be successful when architecting a a full application?
Jenn Creighton: Do you mean in terms of-
Kent C. Dodds: You can talk about maybe file structure or component structure. Where do you store your state and how do you keep things in sync and that kind of thing.
Jenn Creighton: I'm dealing with all of these questions right now at work. So moving into this role of being a front end architect and not just a... I don't want to say "just" actually and not a senior front end engineer contributing to one part of the code base. Now I oversee the code base. I have been sort of falling in love with this, while also realizing that I'm untie untangling a rat's nest of things. I'm coming into a startup where the code base was built by third-party people first. Then they've hired a team, but no one on that team is as senior as I am, overall, and also especially in React.
So a lot of things have been implemented and what I've been trying to do is actually come up with sort of a set of rules by which I'll make decisions architecture-wise, not just to do with components but things like, one of my rules is that an engineer early in their career should be able to come into our code base and get up to speed quickly. And that is an overall rule that really just has to do with consistency in your code base. Because if they can't grep around in the code base, if they can't find that every example of what they might want to do is consistent, it makes it so much harder for them moving forward. So I want to put in place these rules about, "We consistently use this state management library."
Truthfully, right now, we have Redux and then we're using RSAAs and thunks and Rematch. Someone put in place all these different things. So if I have a person come in now, they're finding multiple ways of doing things. So consistency. I really want to be able to look around at how components are built and see that they're being built along sort of the same guidelines.
So I'm starting to hand down some rules and guidelines to my engineers about keeping business logic out of things. Where do we actually do the management of deciding what gets passed down to the components business logic-wise and what changes? So those types of things so that someone can come in and have a good sense of how we build things. If that answers the question.
Kent C. Dodds: Yeah, yeah. And do these rules take the form of some guidelines and principles in some sort of document or do you have a strict set of these are the plugins that you use? How do you kind of guide the engineering so that they follow these rules properly?
Jenn Creighton: I'm starting to put in place some more ESLint rules. We haven't had a lot of them, to date. So we definitely have just like visual inconsistencies in our code, stylistic inconsistencies. So putting those in place. The rest of it though is sort of where I'm able to do this because we're not a large team, but I offer to pair with people. They're welcome to come pair with me at any time. I review a lot of code reviews that I'm not even on or I step in with those things. And then I hold a monthly front end guild meeting where we talk about some of these issues together, about how to build things. I pass on a lot of resources. I ask them to go to conferences, workshops, got them an Egghead course, trying to cram knowledge into my team. So, yeah.
Kent C. Dodds: Just flood them with resources.
Jenn Creighton: Yes. Because in some ways, I say that they're rules, and really they're guidelines. I'm only going to put my foot down every once in awhile. As much as I want consistency, but I also don't give my team freedom to play around with stuff. They're not going to understand why I've asked them to do it a certain way. There is benefit in letting people see that something doesn't work and then revise it later. I personally do not see revision or refactoring as a failure. I think a lot of people do, but I don't.
Kent C. Dodds: I love that. Can you dig into that a little bit more, Jenn? Like why is revision and refactoring not a failure? I've had many times in my career where I've... Let's try this abstraction and it just is a terrible experience for everyone and it takes me a week to backtrack off of that. So why do you see that as not a failure?
Jenn Creighton: I think it's part of the natural course of our jobs. And if you're not doing it, what value are you getting? You need to make the mistakes to learn something and sometimes it's not even that what you wrote was a mistake. It was right maybe for the time, but things change, and so you actually need to go to revisions and refactorings, one, if you're doing this from someone else's code that they wrote, come to it with the best of intentions. Remember that they wrote it under circumstances that you weren't there for.
I think a lot of people, they come in, they see some code, it's not great according to them, and they're like, "Ugh, I have to refactor this. This is bad code." And you don't know what that code was written under, unless you're literally the one that wrote it and then you get to say whatever you want about your old code. I curse myself a lot. But this is the natural form of things. If you build code under tight deadlines and you're new to a framework, you're not going to be putting out your A+ right away things. Your first draft is never the end draft. You're always revising as you go along and you're learning things from those revisions. So I really want people to see refactoring as just a natural progression of our jobs and not a failure at all.
Kent C. Dodds: Yeah, I think that's wonderful. That makes me feel better. So, yeah, really good. So, Jenn, as we're reaching toward the end of our time here, is there anything else about React component architecture or application architecture that you'd like to specifically call out and chat about before we wrap up?
Jenn Creighton: I think mostly what we've talked about. Try writing down the component architecture before you start. Try from the outside to see what your component's going to look like before you actually start to implement it. It's really going to help you lean into that declarative nature that is React, too, it really helps with that. And then remember that you're probably going to write this thing and it may not work and it might work and then a couple of months later you come back to it and you hate yourself for it. It's all fine. It's totally fine. If I go back and look at the components I first wrote five years ago, I will be horrified and I will just stay in my house forever and never leave, except that I have a healthy mindset that I was learning, I was new.
Kent C. Dodds: Yeah, exactly. That's wonderful. So, there you have it, everybody. The call to action or your homework for this episode is for the next component that you write, document that component first. And this isn't just for reusable components, right, Jenn?
Jenn Creighton: Yeah.
Kent C. Dodds: This is something that's useful, even if it's this little widget over here that's only going to be used on this page. Or if you think it's going to be a reusable component, definitely document it first. I like that idea a lot. So, Jenn, what's the best way for people to reach you online?
Jenn Creighton: Definitely Twitter. My handle is gurlcode, gurl spelled with a U. I'm pretty active on there, so you can tweet me.
Kent C. Dodds: Excellent. And if you're ever in New York city, you've got a meetup that people can go to, right?
Jenn Creighton: Yes. So I'm also a co-organizer for the useReactNYC meetup. We just got started earlier this year. We just had our fourth meetup and we're continuing them monthly. Might take a break around the holidays. But if you happen to be in New York, please look us up. We love new faces in our community.
Kent C. Dodds: I spoke two months ago, a month ago, pretty recently, and it was a wonderful experience. So yeah, a strong recommend there. Great. Well, Jenn, thank you so much for giving us some of your time this afternoon or evening or morning, whenever people end up listening to this. I really appreciate your time and I hope that everybody enjoyed hearing you as much as I enjoyed chatting with you. So, thank you. And, yeah, we'll see you all later. Bye friends.
Jenn Creighton: Bye, friends.