O que são React Server Components e como eles funcionam?

React Server Components (RSCs) é uma nova tendência que mudou a forma como os desenvolvedores React abordam as coisas. Com RSCs, mais trabalho é transferido para o servidor, o que traz muitos benefícios. Vamos dar uma olhada no que são os componentes de servidor, como eles funcionam e o que levou à introdução dos componentes de servidor. React Server Components são componentes React que renderizam exclusivamente no servidor, que envia apenas o HTML final para o cliente. Isso significa que esses componentes podem acessar diretamente recursos do lado do servidor e reduzir drasticamente a quantidade de JavaScript enviada para o navegador. Aplicativos React tradicionalmente usam um sistema de "client component" que gerencia tudo em um aplicativo React típico, como renderização, interatividade e efeitos colaterais. O termo "client component" raramente era usado até a introdução recente dos React server components. Mas o sistema de componentes do cliente apresenta algumas desvantagens como grandes pacotes de JavaScript e tempos de carregamento inicial mais lentos. Frameworks React como Next.js e Gatsby encontraram soluções alternativas para descarregar alguns processos para o servidor a fim de corrigir esses problemas, mas nenhum deles foi padronizado. Se você já usou qualquer um dos frameworks, provavelmente já ouviu falar sobre getServerSideProps e getServerData. Então vieram os React Server Components, que permitem executar alguns componentes inteiramente no servidor para que você possa fazer coisas como busca de dados e computação antes que qualquer código seja executado no navegador do usuário. Componentes de servidor foram popularizados inicialmente e estão prontamente disponíveis no Next.js. Outros frameworks como Remix e Gatsby estão alcançando, e há um plugin experimental para Vite chamado vite-plugin-react-server que permite construir componentes de servidor. Então como os componentes do servidor funcionam? Uma das melhores maneiras de demonstrar React Server Components é com a busca de dados. Em componentes cliente tradicionais do React, você deixa o navegador lidar com as requisições de API. Como a busca de dados é um efeito colateral, você faz essa chamada de API em um hook useEffect. Também é uma boa prática definir variáveis de estado como loading, data e error para que você possa indicar que os dados estão carregando, exibir os dados quando estiverem prontos ou mostrar um erro no seu app. Com React Server Components, você pode mover o componente inteiro para o servidor e buscar dados lá sem precisar usar useState ou useEffect:
const Users = async () => {
  const res = await fetch("https://jsonplaceholder.typicode.com/users");
  const users = await res.json();

  return (
    <>
      <h1 className="text-4xl text-center mt-6">Users</h1>
      <ul className="text-center mt-3">
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </>
  );
};

export default Users;
Como os React Server Components só são executados no servidor, você pode simplesmente buscar dados de uma API e renderizar apenas uma vez. Além disso, como a obtenção de dados acontece no servidor, mais próximo da fonte, seu app pode ter um desempenho melhor, especialmente para pessoas com conexões de rede lentas. One major gotcha is that all the code for server components remains on the server, and doesn't get shipped to the browser. Isso significa que você não pode usar React hooks com eles e eles não têm acesso a Web APIs ou listeners de eventos do navegador. Então como você pode adicionar interatividade? No roteador de aplicativos Next.js, todos os componentes são componentes de servidor por padrão. Se você quiser adicionar interatividade, precisa marcar o componente como um client component com a diretiva "use client". Vamos supor que você queira transformar o exemplo anterior em um componente cliente. Aqui está como você pode fazer isso:
"use client";

import { useState, useEffect } from "react";

const Users2 = () => {
  const [status, setStatus] = useState({
    users: [],
    loading: true,
    error: null,
  });

  async function fetchUsers() {
    try {
      const res = await fetch("https://jsonplaceholder.typicode.com/users");
      const data = await res.json();
      setStatus((prevStatus) => ({
        ...prevStatus,
        users: data,
        loading: false,
      }));
    } catch (err) {
      setStatus((prevStatus) => ({
        ...prevStatus,
        error: err.message,
        loading: false,
      }));
    }
  }

  useEffect(() => {
    fetchUsers();
  }, []);

  if (status.loading) {
    return <p>Loading Users...</p>;
  }
  if (status.error) {
    return <p>Error getting users: {status.error}</p>;
  }

  return (
    <>
      <h1 className="text-4xl text-center mt-6">Users</h1>
      <ul className="text-center mt-3">
        {status.users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </>
  );
};

export default Users2;
Se você quiser adicionar interatividade como eventos de clique, o componente também precisa ser marcado como um client component:
"use client";

import { useState } from "react";

const Counter = () => {
  const [count, setCount] = useState(0);

  return (
    <>
      <h1>Counter</h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <h2>{count}</h2>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </>
  );
};

export default Counter;
Se você não adicionar a diretiva use client ao componente, você receberá um erro com uma mensagem que diz "You're importing a server component that needs useState. Este hook do React funciona apenas em um componente cliente. Para corrigir, marque o arquivo (ou seu pai) com a diretiva "use client". Os principais benefícios que vêm com React Server Components são que a obtenção de dados se torna mais simples, o código fica mais fácil de ler e a complexidade do cliente é reduzida.
Este módulo não possui perguntas. Marque como concluído.