diff --git a/content/i-write-big-react-components.mdx b/content/i-write-big-react-components.mdx new file mode 100644 index 00000000..9ff39568 --- /dev/null +++ b/content/i-write-big-react-components.mdx @@ -0,0 +1,19 @@ +--- +title: 'I write big React components' +publishedAt: '2024-03-15' +summary: 'Learn why large React components are not a problem and how to think about component size correctly.' +--- + + + Learn why large React components are not a problem and how to think about component size correctly. + + +When reading articles about React best practices, you’ll learn that it’s better to keep your components small (numbers can vary, but usually 150–200 lines of code is what recommended). The problem is that most articles don't properly explain the reasoning behind this thing, and if followed blindly, it can do more harm than good. So here is my explanation. + +First, and probably most important, instead of thinking about lines of code, you should think about component responsibilities. If your component has a single responsibility, then it’ll be 99% fine to keep things together, no matter how many lines of code it is. And in the case of multiple responsibilities, you’ll most likely want to split the component into smaller pieces that are responsible for a single thing. + +Separating a single component with multiple responsibilities usually comes with performance benefits. Multiple responsibilities mean multiple reasons for a component to re-render, and sometimes it’s not optimal to re-render the whole component’s UI when a tiny piece of state changed. Having components with single responsibilities, you can expect that the UI is updated when it really needed to be updated. + +Obviously, it’s easier to work with a component (read/modify) that has a single responsibility. But at the same time, by refactoring such components into smaller pieces you increase cognitive load (it might be nice to read this top-level piece with a high level of abstractions where everything is moved into custom hooks and subcomponents, but it means more pieces to keep in your head when actually making changes and trying to drill down into all these layers of abstraction). + +In conclusion, I would say that exceptions are possible in both cases. By separating a component into smaller pieces you increase tree nesting which might have its own performance downsides as well as a single large component can have higher time to instantiation, but I hope that now you have a small framework helping you to decide whether to refactor a component into smaller pieces or not. diff --git a/public/images/i-write-big-react-components/opengraph-image.png b/public/images/i-write-big-react-components/opengraph-image.png new file mode 100644 index 00000000..7fef0403 Binary files /dev/null and b/public/images/i-write-big-react-components/opengraph-image.png differ diff --git a/src/app/blog/ViewCounter.tsx b/src/app/blog/ViewCounter.tsx index 088fbfb8..c7315faf 100644 --- a/src/app/blog/ViewCounter.tsx +++ b/src/app/blog/ViewCounter.tsx @@ -5,7 +5,7 @@ interface Props { } async function ViewCounter({ slug }: Props) { - const blogPostViews = await getBlogPostViews(); + const blogPostViews = await getBlogPostViews(slug); const views = blogPostViews[slug]; diff --git a/src/app/globals.css b/src/app/globals.css index c585d1e3..214fb3e7 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -60,7 +60,7 @@ a { } .prose pre { - @apply border border-neutral-800 bg-neutral-900; + @apply border border-neutral-800 !bg-neutral-900; } .prose code { diff --git a/src/app/page.tsx b/src/app/page.tsx index 2691c3f3..19ab039f 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,7 +4,7 @@ import { BASE_URL } from '../utils/const'; import { OG_IMAGE } from '../utils/ogImages'; export const metadata: Metadata = { - title: 'kkurko.dev', + title: 'Kirill Kurko', description: 'Frontend Developer and Penguin 🐧', openGraph: { url: new URL(BASE_URL), diff --git a/src/lib/models/blog.ts b/src/lib/models/blog.ts index f5934805..8ca0c2ca 100644 --- a/src/lib/models/blog.ts +++ b/src/lib/models/blog.ts @@ -11,12 +11,16 @@ export function getAllBlogPosts() { }); } -export async function getBlogPostViews() { +export async function getBlogPostViews(slug: string) { noStore(); - const views = await prisma.blog.findMany(); + const blogViews = await prisma.blog.findFirst({ + where: { + slug, + }, + }); - return Object.fromEntries(views.map((view) => [view.slug, view.views])); + return { [slug]: blogViews?.views ?? 0 }; } export async function trackView(slug: string) {