Criando um Layout Persistente em NextJS
Tags: react, nextjs, beginners, persistentlayout
Published: 2021-05-22 23:44:33

Como da pra notar pelo outros posts, sempre que tenho que implementar algo novo para mim, eu tento postar aqui para ajudar o máximo de pessoas possível e hoje não é diferente! 

Então pega um ☕ e curte o post.

# # Introdução

Podemos dizer que temos um layout persistente quando um componente é compartilhado em diversas telas de nossa aplicação sem sofrer re-renderizações pela troca de páginas. De maneira mais clara é quando declaramos apenas uma vez o componente para ser utilizado em parte ou em toda a aplicação. Um exemplo disso é o cabeçalho e o rodapé de um projeto que são normalmente compartilhados em diversas páginas porém declarados um vez.

# # Explicando o exemplo 🤯

No exemplo que vamos construir aqui, quero além de exibir o cabeçalho em todas as páginas, quero também só que apenas nas páginas que estão dentro da pasta `/pages/minha-conta/*` exibam um menu de navegação lateral. 

Abaixo há uma imagem para explicar melhor o que será desenvolvido.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fpkb85x9y77d2i6eu20e.png)

# # Ao código! 👨‍💻

## ## Adicionando cabeçalho e entendendo o uso de App

Como estamos usando o nextjs para este exemplo, nosso arquivo `_app.js` deve ser parecido com esse:

```jsx
export default function App({ Component, pageProps }) {
  return (
	  <Component {...pageProps} />
  );
}
```

Como você deve saber, toda página que temos em nossa aplicação na hora de sua execução ela será executada como o `Component` acima. 

Por exemplo: temos a página `meus-dados.js` quando o usuário acessar esta página em seu navegador, o *nextjs* "enviará" o componente exportado pela página de `meus-dados.js` para o arquivo `_app.js` . Neste arquivo obtemos o componente a ser executado e suas propriedades (caso tenha), e em seguida o executamos utilizando `<Component />` .

Entendido isso então percebemos que conseguimos envolver este `Component` com um *Fragment Operator* para possibilitar a renderização de qualquer outro componente junto com a página em execução.

Portanto conseguimos adicionar um componente que **será exibido em todas as páginas** de nossa aplicação dessa maneira:

```jsx
export default function App({ Component, pageProps}) {
  return (
    <> 
		  <Header />
	    <Component {...pageProps} />
    </> 
  );
}
```

Show! Cabeçalho adicionado ✅ 👏

## ## Adicionando menu lateral

Para adicionar o menu lateral somente para as páginas que fazem parte da pasta `minha-conta` precisamos realizar mais algumas alterações. 

> A ideia que eu quero aqui é: Declarar apenas uma vez o componente do menu lateral e fazer ele parecer em todas as páginas da pasta `minha-conta` .

Usarei aqui como exemplo as páginas `/pages/minha-conta/meus-dados` e `/pages/minha-conta/alterar-senha` . 

Abaixo fica mais claro o nosso objetivo:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v19yxnkrncn37xujwc56.png)

Precisamos de um filtro para selecionar em qual tela devemos exibir o menu. Não podemos apenas adicionar o componente junto ao cabeçalho como fizemos acima pois senão o menu seria renderizado em todas as telas.

Vamos então construir um novo componente que envolverá todas as páginas que precisamos e nele adicionarmos o componente de menu. Vou chamar de MyAccountLayout esse componente que criaremos. 

```jsx
import SideMenu from '../_components/SideMenu';

const MyAccountLayout = ({ children }) => (
  <>
    <SideMenu />
    { children }
  </>
);

export default MyAccountLayout;
```

Como o componente acima servirá como um *wrapper* precisamos que ele aceite os `children` que são todos os componentes envolvidos por ele.

Agora em todas as páginas que o menu deve aparecer, devemos adicionar uma propriedade no componente a ser exportado. O nome dessa propriedade pode ser qualquer um, eu vou chamar de layout. É nessa propriedade `layout` que vamos adicionar o componente `MyAccountLayout` que criamos acima.

```jsx
//Página de meus-dados

import MyAccountLayout from '../_layout';

const UserData = () => (
  {...}
);

UserData.layout = MyAccountLayout;

export default UserData;
```

Para finalizar, no arquivo _app.js vamos criar um componente para receber o conteúdo da propriedade `layout` caso exista, caso não exista vamos adicionar um *Fragment Operator*. Além disso vamos envolver o `Component` pelo componente criado.

```jsx
export default function App({ Component, pageProps}) {
	const CustomLayout = Component.layout ? Component.layout : React.Fragment;
  return (
    <> 
		  <Header />
	    <CustomLayout>
        <Component {...pageProps} />
      </CustomLayout>
    </> 
  );
}
```

 Com isso já temos o que queríamos! Menu lateral adicionado apenas nas páginas da pasta `minha-conta` .

E o melhor, você consegue fazer qualquer outro layout persistente usando esta mesma técnica, basta criar o componente de seu layout e atribui-lo a propriedade `layout` do componente da página. Show né!

# # Conclusão 😻

Chegamos ao fim de mais um post e então, gostou? 

Sempre busco explicar o máximo que consigo para que todos que leiam entendam o que estamos fazendo e consigam aplicar em seus projetos. 

Sobre a maneira que fizemos o layout persistente, vale salientar que existem inúmeras maneiras de fazer isso, este foi o jeito que mais gostei seguinte as dicas do link nas referências.

See you soon!

# # Referências

- [Persistent Layout Patterns in Next.js](https://adamwathan.me/2019/10/17/persistent-layout-patterns-in-nextjs/)