👋 Hi there! I'm Kent C. Dodds (https://twitter.com/kentcdodds). This is a (week)daily podcast where I give 3 minute thoughts about web development.
You can subscribe on iTunes here: http://kcd.im/3-mins-itunes and on RSS here: http://kcd.im/3-mins-rss
Prisma is amazing
Hey there friends. So yesterday I was just a fanboying I guess about
Prisma. If you haven't heard of Prisma, it is a Oh what does that? It's
ORN, I can't remember what what the word for that is but it interfaces
between you and a backend database. So it supports post-grass and SQLite my
sequel and a MongoDB support is coming.
So yeah, just so you have a database and you tell it what database what
kind of,Database you're hitting and how to connect to it or what the
connection URL is. And then it manages connecting to it and you have the
rest of your code doesn't have to worry about what type of database it is.
You just work with Prisma. And what makes Prisma especially special is that
it has a really great way for defining your schema for the types or the
models that your database supports. It has a really nice way of making the
database match that so it'll create the tables for you and everything.
It has a great way for my great.Hitting so if you need to change the column
name or something then it will automate that process and and that can be
part of your deployment pipeline is to alter tables to add columns and
stuff like that. It doesn't quite help you with like breaking changes.
It they have some articles to help, you know, how to go about doing that
and I have successfully done that with Prisma. But yeah, and and it's it's
not like a terribly difficult thing to do necessarily but I mean if it's a
really great big breaking change then having zero downtime is tricky.
But yeah, I've had a couple like the situations where I needed to remove an
enum value and stuff and I was able to do that without too much trouble.
Thanks to a lot to prism as migrate feature, but then the thing that you
experience on a regular basis working with Prisma that just I love is its
type script support.
So you define this schema and then it generates TypeScript types. So that
as you're using Prisma you say Prisma dot and then the,The table that you
want to get and info from and then find many and then you have a select and
aware and an order by and if there's relations so like a user has many
posts or something then you can get all that users posts or if you're
looking for posts, you can get the the author and data from that and it's
all just so nice with TypeScript.
It's it's brilliant. So if you are using one of those databases and you
haven't tried Prisma yet give it a look it is fantastic. I'm really really
happy with it. Hope you're having an awesome day andWe'll talk to you later.
Using ScriptKit to easily upload images to @cloudinary
Hello friends. So this morning, I finished something that I was working on
a little bit yesterday. It's a script kit script to call Cloud Nary upload
which allows me to very easily upload images to my cloud nary account. It
uses the cloud nary API and yeah, I just need a couple of environment
variables and and you can use this too.
You get script kit, you can copy the same script. And yeah, you just need a
couple environment variables and then it uses the script kit. UI which is
basically kind of like,Spotlight or Alfred where you say I want to run the
culinary upload and then it asks you which folder you want to upload it to
and it gives you this way to navigate around those so you can say on the
I want one folder one directory yep or I want to go into this directory and
so you can kind of navigate the folder structure of cloud nary which is
really useful for me because I know that I could just like throw all of my
blog post images and all of my epic react article images and all of my
other images throughout my site into one giant bucket andReference those
URLs and whatever but I don't know about you I just really like to have
things organized and directory makes the most sense.
And so, you can navigate around the directory as you would expect. You can
create a new directory and I also cash the other folders that are within a
directory so I don't have to hit the API every time you go you're as your
navigating around. And so I give you an option to refresh the cash for a
And and yeah, and so once you've selected your directory, then it gives you
a drag and drop little UI where you can drop as many images.As you like and
then it goes through each one of those images and asks you what you want
the name of the image to be it gives the default for whatever the file name
is And then yeah and then it'll upload it.
And when you're all done, it will open up your browser to show you to the
directory that you chose so that you can see all the images. It also copies
the URL for each image that you uploaded and so if you have if you're just
uploading one then that's the one that's in your code board.
If you upload multiples and they're gonna overwrite each other, which is
why I think it's really good idea to have a clipboard history with Alfred
is is how I do that. And so yeah, I just updated.My 2010 decade and review
posts in their like 20 images in that post and I uploaded those all of
those and updated the blog post in like just five minutes.
It was really nice. So eventually, I'm gonna automate the whole process of
putting all of my images on cautionary for all my blog posts, but this was
a really good first take it what it's gonna be like for writing new blog
posts and uploading new images. So anyway, this is another example of where
script kit is awesome.
I'll put a link to the script in the description and I hope that's
interesting and helpful. Have a nice day.
Avoid Hasty Abstractions: Hooks edition
Hello friends, so I wanted to talk today about whether or not you should
make a custom hook for everything. So a few days ago, maybe last week there
was this thing going around where people were recommending that you never
ever use the react built-in hooks inside of a component, you always extract
it to a custom hook.
This is terrible advice. Don't do that at all. So the way that I think
about hooks in React is the they're basically functions that have the,Only
special distinction of being functions that actually call other hooks.
That's the only thing special about them. So everything else about this
function is the same as regular functions.
And you don't make a function for every line of code that you write right?
Like that would be ridiculous. The reason that we make functions is to
encapsulate certain logic. And most of the time it's useful mostly for
reuse. Sometimes it could be nice to take a bunch of chunks of code.
And logically put it together so that it can be separate from the rest of
our our code, but you've got to keep in mind that every single time you
abstract something into another function you're adding complexity. And now
you have to pass parameters and and maybe you didn't pass enough and so now
you need to update those in the except the additional parameters and and
and then if you're doing TypeScript, you have to make sure that you're
typing for those parameters is correct and and potentially worry about the
return value and then oh what if now weDecide that there's some logic in
this function that says never mind let's return early or let's throw an
error or something like that.
Now, you have to start worrying about the consumer and say, oh well, they
wanted to return early from here. So, I'll return early. It just gets to be
more complex. There are more things to think about. So you can't avoid
adding complexity when you start abstracting things into functions.
It's just the way that it is it always adds complexity. Now whether or not
it makes your code simple or more simple.Is a different matter or sorry let
me say that differently whether or not it makes it easier for you as the
the writer of the coder and the maintainer of the code to understand what's
That's a different matter. But the fact is that it will always increase
complexity to extract things into separate functions and that is no
different with hooks. This is especially relevant if you wanted to abstract
just the use effect part, but you want to pass in some sort of function
that's going to get called within that effect.
That means that you'll either need to.Call back that your passing in or you
have to use the latest ref pattern to always use the latest function. So
anyway, hope that helps.
performance.mark and performance.measure for improved DevTools profiling
Hello there friends. Sorry, it's been a little bit of a break but I was
working on something and I wanted to measure how fast it was but yeah and
so I'm gonna use the Chrome DevTools profiling performance tab to profile
it. And it's always so frustrating to like try and find the part of the
code that you're trying to profile in that flame graph.
It's really kind of a confusing area. And I remembered that there's the
performance mark API and so you have the ability to add your own custom
timings and so,You can say okay here's the start of what I'm trying to
measure and here's the end. And how long did all of that take?
And you can do like performance down now console log in and then like
compare and stuff. But I wanted to look at the flame graph. And so I it
didn't work right away and I looked up and found a stack overflow post that
showed exactly how to do this and so I'll link to that in the notes of this
But basically, it's a combination of the mark and measure APIs on the
performance object. So you say performance dot mark and you give it a
string to label that mark.And then another performance you do whatever it
is you want to do So in my case I wanted to measure the reading time of a
blog post and I'm using this module called reading hyphen time, which I
think is what like all the gaps people logs and everything used for this.
And so I call that function and I'm on a really big blog post and to test
this out. I call that function and then on the next line you say
performance.mark and you give it another label and then you say right after
that performance dot measure and you give three arguments the first is the
The measurement the second is for the start marker So whatever you put for
the first performance dot mark, that's what the second argument here. And
then the last argument is whatever you put for the end. So you give it a
name and then the start in the end and then that will show up in your dev
tools in the performance profiling tab and it just makes it so much easier
to make sure that you're honing in on the area of the code that you
actually care about.
Unfortunately, I don't know whether this works very well for asynchronous
code. So, I cure it's we're gonna do an await here and then afterThat away
I don't think that's gonna work very well But for synchronous code it works
great And actually if we're talking about async code and there is some
performance profiling metrics that you can do with React app specifically
and they do have the ability to do some sort of timings for that with
It's actually very cool and I teach you about it on epic react. So if
you're if you're not done the performance workshop yet, or the actually the
performance section of the bookshelf app, then you may not have run up
against that. But it's really cool. All right, hopefully that's helpful.
I'll chat with you later.
Make your DB schema as restrictive as possible for easier migrations
Hello there friends. Welcome to June I am thinking about Postgres and
Prisma and that sort of thing a lot lately because I'm working on my
website and doing that sort of thing and one tip that I have for you if you
ever do database sort of things is try to make sorry to make your data as.
As restrictive as possible. Early on as as you're trying to make things. So
like make things if you're like, I don't know if there should be a required
field or not make it required. If you're this is an enum but we could have
this we could have a lot of different values for this potentially have the
fewest number of values possible to get you to the next phase.
The reason is because it's a lot easier to later do a migration.That
expands the permissive venous of that schema than going the other direction
because when you go the other direction, you have to find all of the data
rows that don't go into the new schema and update those so that they they
So, for example, if you have a first name field and you decide to make it
optional first and then after you have a bunch of users you come in later
and you decide no no this first name field needs to.Be required. Well, now
you have to first go and update all of the usernames to be like unknown or
something before you can do that schema update.
And so yeah, just try to when you're starting a new project or when you're
yeah, I guess not even a new project but when you're adding a new model or
something like that try to be as restrictive as possible early and then you
can loosen things up later when you have more context and you know, what
makes more sense.
So yeah, hopefully that's helpful and interesting. IIt's this is just
personally affected me because I I was really loose at the start of this
project and then I had to tighten things up and it's kind of annoying. So
anyway, I hope that's interesting helpful. Ah, but a nice day.
Fixating on fixing rerenders
Hello there friends. So today somebody shared a lightbri with me and I
assumed that it was just a library to help you track rerenders. But it
turns out it's like a state management library and that helps you avoid
rerenders but my initial reaction and thought about tracking re-renders is
the tools like that.
I think lead people to jump directly to the natural and obvious solution,
which is often not the best solution and I'm talking about memoization. So
when,If you're tracking rerenders and that's how you measure whether
something's faster or not you're gonna say, oh well this component didn't
need to rerender so therefore.
I will apply the re-render hammer to solve this problem and that is react
memo. And then you have to use memo or use callback all the things that you
pass to it. And that spiders in into the rest of your code base really
easily. And so what I recommend is I have a blog post called fix the slow
render before you fix the rerender and so you have to put a little bit more
thought into it, but you find out what part of you.
Here rendering is slow because even if you fix the rerender at some point
you've got to render like there are necessary renders. And if those are
slow then that's not a great user experience either. And so if you can fix
that then maybe you'll be able to avoid needing to worry about rerenders.
But sometimes you just there's nothing that's slow in particular. It's just
a lot of things that add up to make the experience slower and so fixing
renders is kind of the the best approach for that. And when you're in that
situation, then I actually wrote.Another blog post called state look
colocation can make your react apps faster and just recently wrote a blog
post that takes an angle on the like forms and how you can use state
collocation with forms and I'll link all of those at the top of this the
description this episode.
But basically, I think that we can get a lot by using state co-location
also composability and composing our components, especially like layout
components, so you don't have to pass.Props through all these other you
know app components And as with a combination of the way that you structure
things you often don't have to worry about unnecessary renders because they
just can't happen.
So anyway, the library itself was a state management tool and and some
people get a kick out of that and that's great. That's awesome. I haven't
found myself needing to reach for many state management tools outside of
react query and went with Remix. I don't really need a state management
It's pretty awesome. But yeah, those are just some of the thoughts that I
had when I first saw the name of this librarian. So hope that,Is
interesting and helpful have a nice day.