Full Code of rubenmarcus/guiareact.org for AI

main 74244731e869 cached
16 files
33.2 KB
9.7k tokens
11 symbols
1 requests
Download .txt
Repository: rubenmarcus/guiareact.org
Branch: main
Commit: 74244731e869
Files: 16
Total size: 33.2 KB

Directory structure:
gitextract_igeb4d_j/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── discussion.md
│   └── pull_request_template.md
├── .gitignore
├── README.md
├── components/
│   ├── header.js
│   ├── mdcontainer.js
│   └── pagehead.js
├── config/
│   ├── md-loader.js
│   └── static-paths.js
├── documentation/
│   └── DOC-HOME.md
├── next.config.js
├── package.json
├── pages/
│   ├── _app.js
│   ├── _document.js
│   └── index.js
└── styles/
    └── style.css

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/discussion.md
================================================
---
name: Issue de discussão
about: Sugestões, alterações, correções, etc.
title: ''
labels: ''
assignees: ''

---

## O que?

<!--
  Detalhe qual o assunto da issue, o contexto da mesma e qual o problema à ser resolvido.
  Exemplo: "Precisamos adicionar uma sessão sobre..."
-->

(Escreva aqui.)

## Por quê?

<!--
  Escreva quais são as motivações da issue.
  Exemplo: "Atualmente, não temos uma sessão sobre... e essa sessão é muito importante pois...
-->

(Escreva aqui.)

## Referências

<!--
  Adicione às referências à issue (PR's, documentações, outras issues, etc.)
-->

(Escreva aqui.)


================================================
FILE: .github/pull_request_template.md
================================================
## Descrição

<!--
  Detalhe qual o objetivo desse PR, qual a finalidade do mesmo.
  Exemplo: "Adicionada sessão de ..."
-->

(Escreva aqui.)

## O que foi feito nesse PR?

- [x] Tarefa já realizada
- [ ] Tarefa à ser feita

## Dependência de outras Issues

> Exemplo: #1
> 


================================================
FILE: .gitignore
================================================
./node_modules
node_modules
node_modules/*
./.next
.next

================================================
FILE: README.md
================================================
# guiareact.org 
Site em Português com tradução do Original reactpatterns.com de Michael Chan - [@chantastic](https://github.com/chantastic)

https://guiareact.org


## CONTRIBUA

 - Clone o projeto em sua máquina
 - Edite ou Crie os arquivos MD na pasta **documentation**
 - Abra uma [Issue](https://github.com/rubenmarcus/guiareact.org/issues/new).
 - Crie um [P/R](https://github.com/rubenmarcus/guiareact.org/compare) e adicione o link na sua issue.


## ROADMAP

- TROCAR TODOS EXEMPLOS DE CLASSE PARA EXEMPLOS COM COMPONENTES FUNCIONAIS
- ADICIONAR GUIA DE HOOKS
- ADICIONAR MAIS EXEMPLOS
- ADICIONAR GUIA DE NEXT.JS
- ADICIONAR GUIA DE CSS IN JS
- ADICIONAR GUIA DE REDUX
- ADICIONAR GUIA DE CONTEXT API

================================================
FILE: components/header.js
================================================
export default function AppHeader(props){

    return(
        <header>
            <h1>{props.title}</h1>
            <nav>
              <ul>
                <li>
                  <a
                    className="github-button"
                    href="https://github.com/rubenmarcus/guiareact.org"
                    data-color-scheme="no-preference: light; light: light; dark: dark;"
                    data-size="large"
                    data-show-count="true"
                    aria-label="Star rubenmarcus/guiareact.org on GitHub"
                  >
                    Star
                  </a>
                </li>
              </ul>
            </nav>
          </header>
    )
}

================================================
FILE: components/mdcontainer.js
================================================
import ReactMarkdown from "react-markdown";
import remarkSlug from "remark-slug";
import remarkLinks from "remark-external-links";
import remarkHljs from "remark-highlight.js";
import remarkToc from "remark-toc";

export default function MdContainer({ markdown }) {
  const remarkPluginSet = [remarkSlug, remarkLinks, remarkHljs, remarkToc];

  return <ReactMarkdown children={markdown} remarkPlugins={remarkPluginSet} />;
}


================================================
FILE: components/pagehead.js
================================================
export default function PageHead(props) {
  const GA_TRACKING_ID = "G-TQFVHD7RW1";

  return (
    <>
      <title key="title">{props.title? props.title : 'Guia de Padrões React'}</title>
      <meta
        name="viewport"
        content="initial-scale=1.0, width=device-width"
        key="viewport"
      />
      <meta
        key="description"
        name="description"
        content="Guia de Padrões React.Com exemplos e padrões básicos a avançados."
      />
      <link
        href="https://fonts.googleapis.com/css?family=Merriweather:300,300i&display=swap"
        rel="stylesheet"
      />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <meta name="apple-mobile-web-app-capable" content="yes" />
      <link rel="apple-touch-icon" href="/logo-180x180.png" />
      <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
      <meta name="apple-mobile-web-app-title" content="Guia de Padrões React" />
      <script
        async
        src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
      ></script>
      <script async defer src="https://buttons.github.io/buttons.js"></script>
      <script
        dangerouslySetInnerHTML={{
            __html: `
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
    gtag('config', '${GA_TRACKING_ID}');
    `,
        }}
      />
    </>
  );
}

================================================
FILE: config/md-loader.js
================================================
import Hooks from "../documentation/DOC-HOOKS.md";
import Contribua from "../documentation/DOC-CONTRIBUA.md";
import Links from "../documentation/DOC-LINKS.md";

const MdLoader = {
  hooks: Hooks,
  contribua: Contribua,
  links: Links,
};

export default MdLoader;


================================================
FILE: config/static-paths.js
================================================
const ROUTES = [
  { params: { slug: "hooks", title: "Guia de Hooks" } },
  { params: { slug: "contribua", title: "Guia de Padrões React" } },
  { params: { slug: "links", title: "Guia de Padrões React" } },
];

export const STATIC_PATHS = { paths: ROUTES, fallback: false };

export const PATH_PROPS = (slug) =>
  STATIC_PATHS.paths.filter(({ params }) => params.slug === slug)[0].params;

================================================
FILE: documentation/DOC-HOME.md
================================================
# Guia de Padrões React

Um guia de padrões React em Português.

Baseado no [Original](https://reactpatterns.com) por Michael Chan [@chantastic](https://github.com/chantastic)

Traduzido para Português e revisado por [@rubenmarcus](https://github.com/rubenmarcus)

com contribuição de [@LhuizF](https://github.com/LhuizF), [@matheusinfo](https://github.com/matheusinfo), [@luizwbr](https://github.com/luizwbr), [@arimariojesus](https://github.com/arimariojesus), [@gabepinheiro](https://github.com/gabepinheiro), [@GusttavoCastilho](https://github.com/GusttavoCastilho) e [@azraelgarden](https://github.com/azraelgarden).

## Conteúdo

- [Traduções](#traduções)
- [Elementos](#elementos)
- [Componentes](#componentes)
- [Fragmentos](#fragmentos)
  - [Sintaxe curta](#sintaxe-curta)
  - [Exemplo com lista de componentes](#exemplo-com-lista-de-componentes)
- [Expressões](#expressões)
- [Props (Propriedades)](#props-propriedades)
- [defaultProps (Propriedades Padrão)](#defaultprops-propriedades-padrão)
- [Desestruturando props](#desestruturando-props)
- [Atributos de spread JSX](#atributos-de-spread-jsx)
- [Mergeando props desestruturadas com outros valores](#mergeando-props-desestruturadas-com-outros-valores)
- [Renderização Condicional](#renderização-condicional)
  - [`if`](#if)
  - [`unless` (ao menos que)](#unless-ao-menos-que)
  - [`if-else` (Operador Ternário)](#if-else-operador-ternário)
- [Tipos de filhos (Children Types)](#tipos-de-filhos-children-types)
  - [`String`](#string)
  - [`Array`](#array)
- [Array como filho (Array as children)](#array-como-filho-array-as-children)
- [Função como filha (Function as children)](#função-como-filha-function-as-children)
- [Render prop](#render-prop)
- [Passando um Filho (Children)](#passando-um-filho-children)
- [Componente Proxy](#componente-proxy)
- [Estilizando componentes](#estilizando-componentes)
- [Switch de Eventos](#switch-de-eventos)
- [Componente de Layout](#componente-de-layout)
- [Container Components](#container-components)
- [Higher-order components](#higher-order-components)
- [Elevando o state (state hoisting)](#elevando-o-state-state-hoisting)
- [Inputs Controlados](#inputs-controlados)

## Traduções

Traduções não verificadas, e links não significam que são aprovadas.

[Chinese](https://reactpatterns.cn)

## Elementos

[Elementos](https://pt-br.reactjs.org/docs/glossary.html#elements) são tudo que está envolvido por <>.

```jsx
<div></div>
<MeuComponente />
```

[Componentes](#componentes) retornam Elementos.

## Componentes

Um [Componente](https://pt-br.reactjs.org/docs/glossary.html#components) é definido por uma função que declarada retorna um [Elemento](#elementos) React.

```jsx
function MeuComponente() {
  return <div>Olá Mundo</div>;
}
```

## Fragmentos

Um [Fragmento](https://pt-br.reactjs.org/docs/fragments.html) permite agrupar uma lista de filhos sem adicionar nós extras ao DOM.

```jsx
function MeuComponente() {
  return (
    <React.Fragment>
      <div>Olá</div>
      <div>Mundo</div>
    </React.Fragment>
  );
}
```

Isto renderizará no DOM apenas os seguintes elementos:

```html
<body>
  <div>Olá</div>
  <div>Mundo</div>
</body>
```

### Sintaxe Curta

Existe uma sintaxe nova e mais curta que você pode utilizar para declarar fragmentos. São as tags vazias:

```jsx
function MeuComponente() {
  return (
    <>
      <div>Olá</div>
      <div>Mundo</div>
    </>
  );
}
```

## Expressões

Use chaves para [Incorporar expressões](https://pt-br.reactjs.org/docs/introducing-jsx.html#embedding-expressions-in-jsx) no [JSX](https://pt-br.reactjs.org/docs/glossary.html#jsx).

```jsx
function OlaUsuario() {
  const nome = "Ruben";

  return <div>Olá {nome}!</div>;
}
```

## Props (Propriedades)

Entenda como `props` como um argumento externo para possibilitar customizações para seu componente.

```jsx
function DigaOla(props) {
  return <div>Olá {props.nome}!</div>;
}
```

## defaultProps (Propriedades Padrão)

Especificar valores padrão de `props` com `defaultProps`.

```jsx
function OlaUsuario(props) {
  return <div>Olá {props.nome}!</div>;
}
OlaUsuario.defaultProps = {
  nome: "Visitante",
};
```

## Default function parameters (parâmetros predefinidos de uma função)

Especificar valores padrão de `props` com `default function parameters`.
Os parâmetros predefinidos de uma função permitem que parâmetros regulares sejam inicializados com valores iniciais caso `undefined` ou nenhum valor seja passado.

```jsx
// Utilizamos aqui uma desestruturação no objeto `props` para pegarmos a prop `nome`
function OlaUsuario({ nome = "Visitante" }) {
  return <div>Olá {nome}!</div>;
}
```

---

## Desestruturando props

[Atribuição via desestruturação](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) é um recurso do Javascript moderno.

Foi adicionado a linguagem no ES2015.

```js
const usuario = { nome: "Ruben" };
const { nome } = usuario;
```

Funciona com Array também.

```js
const numeros = ["um", "dois"];
const [um, dois] = numeros;
```

Atribuição via desestruturação (Destructuring assignment) é usado muito em [componentes funcionais](#function-component).
Essas declarações de componente são equivalentes.

```jsx
const Ola = (props) => <div>Olá {props.name}!</div>;

const Ola = ({ name }) => <div>Olá {name}!</div>;
```

Existe uma sintaxe para atribuir as `props` restantes em um objeto.
Se chama [Parâmetros](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Functions/rest_parameters) e parece assim:

```jsx
const Ola = ({ name, ...restProps }) => <div>Olá {name}!</div>;
```

Esses três pontos (`...`) pegam todas a props que faltam e atribuem ao parâmetro `restProps`.

Então o que fazer com `restProps` quando você o tem?

Continue lendo...

---

## Atributos de spread JSX

Atributos de Spread é uma feature do [JSX](https://pt-br.reactjs.org/docs/introducing-jsx.html).
É uma sintaxe para fornecer as propriedades de um objeto como atributos JSX.

Seguindo o exemplo de [Destructuring props](#desestruturando-props),
Podemos fazer **spread** com `restProps` em nossa `<div>`.

```jsx
const Ola = ({ name, ...restProps }) => {
  return <div {...restProps}>Hi {name}!</div>;
};
```

Isso torna a função `Ola` super flexível.
Podemos passar atributos DOM para `Ola` e que eles vão ser passados a nossa `div`.

```jsx
<Ola name="Fancy pants" className="fancy-greeting" id="user-greeting" />
```

Atribuição via desestruturação é popular porque fornece uma maneira de separar props específicas de componentes, de atributos específicos de plataforma / DOM.

```jsx
function Greeting({ name, ...platformProps }) {
  return <div {...platformProps}>Hi {name}!</div>;
}
```

---

## Mergeando props desestruturadas com outros valores

Componentes são abstrações.
Boas abstrações permitem extensão.

Considere esse componente que usa um atributo `class` para estilizar um `button`.

```jsx
function MyButton(props) {
  return <button className="btn" {...props} />;
}
```

Isso funciona muito bem até tentarmos estendê-lo com outra classe.

```jsx
<MyButton className="delete-btn">Delete...</MyButton>
```

Nesse caso, `delete-btn` substitui `btn`.

A ordem importa para [Atributos de spread JSX](#atributos-de-spread-jsx).
O `props.className` sendo passado, substitui o `className` do nosso componente.

Podemos mudar a ordem, mas agora o `className` **nunca** vai ser nada além de `btn`.

```jsx
function MyButton(props) {
  return <button {...props} className="btn" />;
}
```

Precisamos usar a atribuição via desestruturação para obter o `className` e mergear com o `className` base.
Podemos fazer isso simplesmente adicionando todos os valores a uma array e juntando-os com um espaço..

```jsx
function MyButton({ className, ...props }) {
  const classNames = ["btn", className].join(" ");

  return <button className={classNames} {...props} />;
}
```

Para não ter problemas com `undefined` aparecendo no seu `className`, você pode atualizar sua lógica para pegar valores booleanos `falso`:

```jsx
function MyButton({ className, ...props }) {
  const classNames = ["btn", className].filter(Boolean).join(" ").trim();

  return <button className={classNames} {...props} />;
}
```

Porém, lembre-se de que, se um objeto vazio for passado, ele também será incluído na classe, resultando em: `btn [object Object]`.

A melhor abordagem é fazer uso de packages disponíveis, como [classnames](https://www.npmjs.com/package/classnames) ou [clsx](https://www.npmjs.com/package/clsx),que poderia ser usado para unir nomes de classe, evitando que você tenha que lidar com isso manualmente.

## Renderização Condicional

Você não consegue usar if else em suas declarações de componente..
Então vocês pode usar o operador ternário [conditional (ternary) operator](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) ou [short-circuit](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Short-circuit_evaluation) tranquilamente.

### `if`

```jsx
{
  !!condition && <span>Irá renderizar quando for `verdadeiro`</span>;
}
```

Dica não utilize if dessa maneira:

```jsx
{
  condition && <span>Renderiza quando `verdadeiro`</span>;
}
```

O React pode imprimir um `0` no seu componente. Quando vem `0` nos seus dados, ele não considera sua variável como falsa, utilizando o !! , ele converte 0 para falso

### `unless` (ao menos que)

```jsx
{
  condition || <span>Renderizado quando `falso`</span>;
}
```

### `if-else` (Operador Ternário)

```jsx
{
  condition ? (
    <span>Renderizado quando for `verdadeiro`</span>
  ) : (
    <span>Renderizado quando for `falso`</span>
  );
}
```

## Tipos de filhos (Children Types)

O React consegue renderizar `children` da maioria dos tipos.
Na maioria dos casos é um `array` ou uma `string`.

### `String`

```jsx
<div>Olá Mundo!</div>
```

### `Array`

```jsx
<div>{["Olá ", <span>Mundo</span>, "!"]}</div>
```

## Array como filho (Array as children)

Prover um array como `children` é muito comum.
É como as listas são renderizadas no React.

Usamos o método `map()` para criar um array de elementos React para cada valor da array.

```jsx
<ul>
  {["primeiro", "segundo"].map((item) => (
    <li>{item}</li>
  ))}
</ul>
```

Esse é o equivalente a renderizar um `array` literal.

```jsx
<ul>{[<li>primeiro</li>, <li>segundo</li>]}</ul>
```

Este padrão pode ser combinado com desestruturação, Atributos de Spread JSX e outros componentes, para alguma coesão mais séria.

```jsx
<ul>
  {arrayOfMessageObjects.map(({ id, ...message }) => (
    <Message key={id} {...message} />
  ))}
</ul>
```

## Função como filha (Function as children)

Componentes React não suportam funções como `children`.
Porém com o padrão, [render props](#render-prop) conseguimos criar componentes que tomam funções como `children` filhas.

## Render prop

Aqui um componente que utiliza `render callback`.
Não é útil, mas é um exemplo fácil para começar.

```jsx
const Width = ({ children }) => children(500);
```

Esse componente chama `children` como função, com alguns argumentos, nesse caso o número `500`.

Para usar esse componente estamos utilizando uma [Função como filha (Function as children)](#função-como-filha-function-as-children).

```jsx
<Width>{(width) => <div>window é {width}</div>}</Width>
```

Recebemos esse output.

```jsx
<div>window é 500</div>
```

Com esta configuração, podemos usar essa prop `width` para fazer decisões de renderização.

```jsx
<Width>
  {(width) =>
    width > 600 ? <div>condição de largura mínima atingida!</div> : null
  }
</Width>
```

Se planejamos usar muito essa condição, podemos definir outros componentes para encapsular a lógica reutilizada.

```jsx
const MinWidth = ({ width: minWidth, children }) => (
  <Width>{(width) => (width > minWidth ? children : null)}</Width>
);
```

Claro que um componente `Width` estático não é útil, mas aquele que observa o window do navegador é. Aqui está um exemplo de implementação.

```jsx
function WindowWidth({ children }) {
  const [width, setWidth] = useState(0);

  useEffect(() => {
    setWidth(window.innerWidth);
    window.addEventListener("resize", ({ target }) =>
      setWidth(target.innerWidth)
    );
  }, []);

  return children(width);
}
```

Muitos desenvolvedores preferem [Higher Order Components](#higher-order-components) para este tipo de funcionalidade. É uma questão de preferência.

## Passando um Filho (Children)

Você pode criar um componente projetado para usar `context` e renderizar `children`.

```jsx
class SomeContextProvider extends React.Component {
  getChildContext() {
    return { some: "context" };
  }

  render() {
    // como retornamos children?
  }
}
```

Você está diante de uma decisão. Envolver os `filhos` em uma `<div />` estranha que retorne o `children` diretamente. As primeiras opções adicionam marcação extra (que pode quebrar alguns css). O segundo resultará em erros inúteis.

```jsx
// option 1: extra div
return <div>{children}</div>;

// option 2: erros inúteis
return children;
```

É melhor tratar `children` como um tipo de dados opaco. O React fornece `React.Children` para lidar com `children` apropriadamente.

```jsx
return React.Children.only(this.props.children);
```

## Componente Proxy

_(Não tenho certeza se esse nome faz sentido)_

Os botões estão em todos os lugares nos aplicativos da web. E cada um deles deve ter o atributo `type` definido como `button` .

```jsx
<button type="button">
```

Escrever este atributo centenas de vezes pode trazer muitos erros.
Podemos escrever um High Level Component para passar `props` para um componente de `button` de nível inferior.

```jsx
const Button = props =>
  <button type="button" {...props}>
```

Podemos usar `Button` no lugar `button` e garantir que o atributo `type` vai ser sempre aplicado.

```jsx
<Button />
// <button type="button"><button>

<Button className="CTA">Enviar Dinheiro</Button>
// <button type="button" class="CTA">Enviar Dinheiro</button>
```

## Estilizando componentes

Esse é um [Proxy component](#proxy-component) aplicado às práticas de estilo.

Então temos um botão. Ele usa classes para serem estilizadas como um botão "principal".

```jsx
<button type="button" className="btn btn-primary">
```

Podemos gerar esse resultado usando alguns componentes de propósito único.

```jsx
import classnames from "classnames";

const PrimaryBtn = (props) => <Btn {...props} primary />;

const Btn = ({ className, primary, ...props }) => (
  <button
    type="button"
    className={classnames("btn", primary && "btn-primary", className)}
    {...props}
  />
);
```

Pode ajudar a visualizar isso.

```jsx
PrimaryBtn()
  ↳ Btn({primary: true})
    ↳ Button({className: "btn btn-primary"}, type: "button"})
      ↳ '<button type="button" class="btn btn-primary"></button>'
```

Usando esses componentes, todos eles resultam no mesmo resultado.

```jsx
<PrimaryBtn />
<Btn primary />
<button type="button" className="btn btn-primary" />
```

Isso pode ser uma grande vantagem para a manutenção do estilo. Ele isola todas as preocupações de estilo em um único componente.

## Switch de Eventos

Quando criamos Event Handlers (Controladores de Eventos) é comum nomeá-los assim:`handle{eventName}`.

```jsx
handleClick(e) { /* do something */ }
```

Para componentes que controlam vários tipos de eventos, essas funções podem ser tornar repetitivas.
os nomes podem não trazer muito valor, pois na verdade são proxy de outras ações/funções.

```jsx
handleClick() { require("./actions/doStuff")(/* action stuff */) }
handleMouseEnter() { this.setState({ hovered: true }) }
handleMouseLeave() { this.setState({ hovered: false }) }
```

Considere escrever um unico Controlador de eventos e fazer o switch com o `event.type`.

```jsx
handleEvent({type}) {
  switch(type) {
    case "click":
      return require("./actions/doStuff")(/* action dates */)
    case "mouseenter":
      return this.setState({ hovered: true })
    case "mouseleave":
      return this.setState({ hovered: false })
    default:
      return console.warn(`No case for event type "${type}"`)
  }
}
```

Para componentes simples você pode chamar funções importadas de componentes direto, usando arrow functions.

```jsx
<div onClick={() => someImportedAction({ action: "DO_STUFF" })}
```

## Componente de Layout

Os componentes de layout resultam em alguma forma de elemento DOM estático. Pode não ser necessário atualizar com frequência, ou nunca.

Considere um componente que renderize dois `children` lado a lado

```jsx
<HorizontalSplit
  startSide={<SomeSmartComponent />}
  endSide={<AnotherSmartComponent />}
/>
```

Podemos otimizar agressivamente esse componente.

Embora `HorizontalSplit` seja `pai` para ambos os componentes, nunca será seu `dono`. Podemos dizer para ele nunca atualizar, sem interromper o `lifecycle` dos componentes internos.

```jsx
const HorizontalSplit = ({ startSide, endSide }) => {
  return (
    <FlexContainer>
      <div>{startSide}</div>
      <div>{endSide}</div>
    </FlexContainer>
  );
}

export default memo(HorizontalSplit);
```

## Container Components

"Um container faz a busca de dados e, em seguida, renderiza seu subcomponente correspondente. É isso." - [Jason Bonta](https://twitter.com/jasonbonta)

Olhando esse componente `CommentList`.

```jsx
const CommentList = ({ comments }) => (
  <ul>
    {comments.map((comment) => (
      <li>
        {comment.body}-{comment.author}
      </li>
    ))}
  </ul>
);
```

Podemos criar um novo componente responsável por buscar dados e renderizar o componente `CommentList`

```jsx
const CommentListContainer = () => {
  const [comments, setComments] = useState([])

  useEffect(() => {
    const fetchComments = async () => {
       try {
          const response = await fetch("/my-comments.json");
          const data = await response.json();
          setComments(data);

       } catch (error) {
          console.log("error: ", error);
       }

    fetchComments();
  }, [])

  return <CommentList comments={comments} />
}
```

Podemos escrever diferentes containers para diferentes contextos de aplicação.

## Higher-order components

Uma [higher-order function](https://pt-br.reactjs.org/docs/higher-order-components.html) é uma função que recebe e / ou retorna uma função. Não é mais complicado do que isso. Então, o que é um High Order Component?

Se você já estiver usando [componentes container](#container-component), esses são apenas containers genéricos, envolvidos em uma função.

Vamos começar com nosso componente `Ola` .

```jsx
const Ola = ({ name }) => {
  if (!name) {
    return <div>Conectando...</div>;
  }

  return <div>Olá {name}!</div>;
};
```

Se obtiver `props.name`, ele renderizará esses dados. Caso contrário, irá renderizar "Conectando ...".

Agora, para o dado de ordem superior.

```jsx
const Connect = (ComposedComponent) => {
  const [name, setName] = useState("");

  useEffect(() => {
    // Isso seria um "fetch" ou uma conexão com a "store"
    setName("Michael");
  }, []);

  return <ComposedComponent {...props} name={name} />;
};
```

Esta é apenas uma função que retorna o componente que renderiza o componente que passamos como um argumento.

Última etapa, precisamos envolver nosso componente `Ola` em `Connect`.

```jsx
const ConnectedMyComponent = Connect(Ola);
```

Este é um padrão poderoso para fazer requisições ( fetch ) e fornecer dados para qualquer número de componentes funcionais.

## Elevando o state (state hoisting)

Aqui temos um componente contador, que vai passar seu state para o componente pai

```jsx
import React, { useState } from "react";

function Counter(props) {
  const {
    count: [count, setCount],
  } = {
    count: useState(0),
    ...(props.state || {}),
  };

  return (
    <div>
      <h3>{count}</h3>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}
```

na nossa função App, escutamos o state através da props state do componente `Counter`

```jsx
function App() {
  const [count, setCount] = useState(0);

  return (
    <div className="App">
      <h2>Estado</h2>
      <Counter state={{ count: [count, setCount] }} />
    </div>
  );
}
```

na teoria poderiamos passar esse estado do componente filho, para qualquer outro componente irmão dele.

## Inputs Controlados

É difícil falar sobre inputs controlados em abstrato.
Vamos começar com um input não controlado (normal) e partir daí.

```jsx
<input type="text" />
```

Quando você mexe com esse input no navegador, você vê suas alterações.

Isto é o normal.

Um input controlado desabilita as mutações do DOM que tornam isso possível.
Você seta o `value` do input no escopo do componente e ele não altera no escopo do DOM.

```jsx
<input type="text" value="Isso não será alterado. Tente." />
```

Obviamente, os inputs estáticos não são muito úteis para seus usuários.
Então derivamos o `value` do state.

```jsx

function ControlledNameInput () {

  const [name, setName] = useState("");

  return <input type="text" value={name} />;
}
```

Então, mudar o input é uma questão de mudar o estado do componente.

```jsx
return (
  <input type="text" value={name} onChange={(e) => setName(e.target.value)} />
);
```

Este é um input controlado.
Ele apenas atualiza o DOM quando o estado é alterado em nosso componente.
Isso é inestimável ao criar interfaces de usuário consistentes.

_Se está usando componentes funcionais para elementos de form,
leia sobre [state hoisting](#state-hoisting) para mover o state do componente acima no tree._


================================================
FILE: next.config.js
================================================
module.exports = {
  webpack: (config) => {
    config.module.rules.push({
      test: /\.md$/,
      use: 'raw-loader',
    });
    return config;
  },
};

================================================
FILE: package.json
================================================
{
  "name": "guiareact.org",
  "version": "0.0.1",
  "description": "Guia de Padrões React em Português.Baseado no React Patterns de Michael Chan.",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "next",
    "build": "next build",
    "start": "next start",
    "export": "npm run build && next export"
  },
  "repository": {
    "type": "git",
    "url": "git+ssh://git@github.com/rubenmarcus/guiareact.org.git"
  },
  "author": "Michael Chan <mijoch@gmail.com>, Ruben Marcus<ruben@rubenmarcus.dev>",
  "license": "BY-NC-SA",
  "bugs": {
    "url": "https://github.com/rubenmarcus/guiareact.org/issues"
  },
  "homepage": "https://github.com/readme/guiareact.org#readme",
  "dependencies": {
    "highlight.js": "^11.0.1",
    "next": "^10.2.3",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-markdown": "^6.0.2",
    "remark-external-links": "^4.0.0",
    "remark-highlight.js": "^5.1.0",
    "remark-slug": "^5.1.1",
    "remark-toc": "^5.1.1"
  },
  "devDependencies": {
    "file-loader": "^1.1.11",
    "postcss": "^8.3.5",
    "raw-loader": "^4.0.2"
  }
}


================================================
FILE: pages/_app.js
================================================
import React from "react";
import "highlight.js/styles/atom-one-dark-reasonable.css";
import "../styles/style.css";

function GuiaReactApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default GuiaReactApp

================================================
FILE: pages/_document.js
================================================
import Document, { Html, Head, Main, NextScript } from "next/document";
import PageHead from "../components/pagehead";
import AppHeader from "../components/header";

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    let pageProps = null;

    const originalRenderPage = ctx.renderPage;
    ctx.renderPage = () =>
      originalRenderPage({
        enhanceApp: (App) => (props) => {
          pageProps = props.pageProps;
          return <App {...props} />;
        },
        enhanceComponent: (Component) => Component,
      });

    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps, pageProps };
  }

  render() {
    const { pageProps } = this.props;
    return (
      <Html>
        <Head>
          <PageHead title={pageProps.title} />
        </Head>
        <body className={`guiaPadroes ${pageProps.cssClass}`}>
          <AppHeader title={pageProps.title} />
          <main>
            <Main />
          </main>

          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;


================================================
FILE: pages/index.js
================================================
import Markdown from "../documentation/DOC-HOME.md"
import MdContainer from "../components/mdcontainer"


export default function Page(){
 return (<MdContainer markdown={Markdown} /> )
}

export async function getStaticProps(context) {
  return {
    props: {
      cssClass: 'home',
      title: 'Guia de Padrões React'
    }, 
  }
}

================================================
FILE: styles/style.css
================================================
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap");

html {
  box-sizing: border-box;
}
*,
:after,
:before {
  box-sizing: inherit;
}
html {
  -webkit-font-smoothing: antialiased;
}
::marker {
  font-size: 12px;
}
header {
  background: #20232a;
  top: 0px;
  width: 100%;
  padding: 12px 85px;
  align-items: center;
  height: 70px;
  font-weight: 600;
  color: #61dafb;
  display: flex;
}
header h1 {
  color: #61dafb;
}
header ul {
  display: flex;
  flex-wrap: nowrap;
}
header li {
  list-style: none;
  margin-right: 41px;
  line-height: 15px;
  line-height: 22px;
}
header a {
  color: #fff;
  background: transparent;
  font-weight: 400;
}
header a:hover {
  color: #61dafb;
}
.guiaPadroes div h1:first-child {
  background: #20232a;
  top: 0px;
  width: 100%;
  padding: 12px 85px;
  margin: 0px;
  left: 0px;
  font-weight: 600;
}
.guiaPadroes div p:nth-child(3),
.guiaPadroes div p:nth-child(4),.guiaPadroes div p:nth-child(5) {
  background: #fff;
  font-weight: 400;
  font-size: 16px;
  width: 100%;
  padding-left: 85px;
}

h2#conteúdo {
  margin-top: 3vw;
}

.guiaPadroes div p:nth-child(5) {
  margin-top: 0px;
  padding-bottom: 20px;
}
.guiaPadroes div p:nth-child(4) {
  margin: 0;
  padding-bottom: 30px;
}

code {
  background: rgba(255, 229, 100, 0.2);
  padding: 0.25em 0.25em;
  margin: -0.25em 0;
}

.guiaPadroes div h1:first-child + p {
  background: #fff;
  top: 38px;
  left: 0px;
  width: 100%;
  padding: 25px 85px;
  margin: 0;
}
.guiaPadroes div h1:first-child {
  color: #61dafb;
}
.guiaPadroes p,
.guiaPadroes h2,
.guiaPadroes ul,
.guiaPadroes pre,
.guiaPadroes h3 {
  padding-left: 85px;
  padding-right: 35px;
}
.guiaPadroes ul p {
  padding-left: 0px;
}
.guiaPadroes ul li ul {
  padding-left: 20px;
}
.guiaPadroes div h1:first-child a {
  position: absolute;
  right: 30px;
  top: 18px;
  background: #000;
  color: #fff;
}
a {
  background-color: rgba(187, 239, 253, 0.3);
  border-bottom: 1px solid rgba(0, 0, 0, 0.2);
  color: #1a1a1a;
  display: inline-block;
  font-size: 16px;
  text-decoration: none;
}
p,
pre {
  padding: 5px;
}

body {
  font-size: 16px;
  margin: 0;
  color: #111;
  background: #f4f4f4;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  line-height: 1.4;
}

h1,
h2 {
  color: #282c34;
  font-weight: 500;
}
@media (min-width: 0) {
  body {
    font-size: 16px;
  }
}
@media (min-width: 480px) {
  body {
    font-size: 18px;
  }
}
@media (min-width: 720px) {
  body {
    font-size: 20px;
  }
}
@media (min-width: 960px) {
  body {
    font-size: 22px;
  }
}
@media (min-width: 1200px) {
  body {
    font-size: 24px;
  }
}
h1,
h2,
h3,
h4,
h5,
h6 {
  font-size: 1em;
}
h2 {
  margin-top: 6vw;
}
p {
  /* font-family: Athelas, Georgia, serif; */
  font-size: 0.9em;
  line-height: 1.3em;
  /* max-width: 32em; */
}
pre,
code {
  display: table;
  font-family: source-code-pro, Menlo, Monaco, Consolas, Courier New, monospace;
}
code,
pre {
  font-size: 22px;
  border-radius: 6px;
  margin: 19px;
}
code,
.highlight pre {
  font-size: 0.9em;
}
#contents + ul {
  text-decoration: none;
  padding-left: 20px;
}
.black-link,
#contents + ul li a {
  color: #000;
  text-decoration: none;
}
.black-link,
#contents + ul li a:hover {
  text-decoration: underline;
}
.highlight {
  margin: 1rem 0;
}
.hljs {
  border: 1px solid rgba(0, 0, 0, 0.1);
  padding: 1em;
  margin-top: 1em;
  margin-right: 0;
  margin-bottom: 1em;
  margin-left: -1em;
  font-size: 0.85em;
  /* max-width: 32em; */
}
code {
  display: inline-block;
  margin: 0;
}
hr {
  margin-top: 2em;
  border-color: rgba(0, 0, 0, 0.4);
  border-width: 0;
  border-bottom-width: 1px;
  max-width: 16em;
}
.guiaPadroes ul {
  padding-left: 119px;
}
.guiaPadroes div p:nth-child(3) {
  margin: 0;
}

#guia-de-padrões-react {
  display: none;
}

.guiaPadroes main > div > h1 {
  display: none;
}

@media only screen and (max-width: 780px) {
  code {
    max-width: 68vw;
    font-size: 0.6em !important;
  }

  header {
    width: 100vw;
    padding: 12px 5vw;
  }

  header nav {
    position: absolute;
    right: 0px;
  }

  .guiaPadroes div h1:first-child + p {
    padding: 25px 5vw;
  }
  .guiaPadroes div p:nth-child(3),
  .guiaPadroes div p:nth-child(4) {
    padding-left: 5vw;
  }
  .guiaPadroes p,
  .guiaPadroes h2,
  .guiaPadroes ul,
  .guiaPadroes pre,
  .guiaPadroes h3 {
    padding-left: 5vw;
  }

  .guiaPadroes ul {
    padding-left: 15vw;
  }
}
Download .txt
gitextract_igeb4d_j/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── discussion.md
│   └── pull_request_template.md
├── .gitignore
├── README.md
├── components/
│   ├── header.js
│   ├── mdcontainer.js
│   └── pagehead.js
├── config/
│   ├── md-loader.js
│   └── static-paths.js
├── documentation/
│   └── DOC-HOME.md
├── next.config.js
├── package.json
├── pages/
│   ├── _app.js
│   ├── _document.js
│   └── index.js
└── styles/
    └── style.css
Download .txt
SYMBOL INDEX (11 symbols across 7 files)

FILE: components/header.js
  function AppHeader (line 1) | function AppHeader(props){

FILE: components/mdcontainer.js
  function MdContainer (line 7) | function MdContainer({ markdown }) {

FILE: components/pagehead.js
  function PageHead (line 1) | function PageHead(props) {

FILE: config/static-paths.js
  constant ROUTES (line 1) | const ROUTES = [
  constant STATIC_PATHS (line 7) | const STATIC_PATHS = { paths: ROUTES, fallback: false };

FILE: pages/_app.js
  function GuiaReactApp (line 5) | function GuiaReactApp({ Component, pageProps }) {

FILE: pages/_document.js
  class MyDocument (line 5) | class MyDocument extends Document {
    method getInitialProps (line 6) | static async getInitialProps(ctx) {
    method render (line 23) | render() {

FILE: pages/index.js
  function Page (line 5) | function Page(){
  function getStaticProps (line 9) | async function getStaticProps(context) {
Condensed preview — 16 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (37K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/discussion.md",
    "chars": 596,
    "preview": "---\nname: Issue de discussão\nabout: Sugestões, alterações, correções, etc.\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n## O"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 275,
    "preview": "## Descrição\n\n<!--\n  Detalhe qual o objetivo desse PR, qual a finalidade do mesmo.\n  Exemplo: \"Adicionada sessão de ...\""
  },
  {
    "path": ".gitignore",
    "chars": 56,
    "preview": "./node_modules\nnode_modules\nnode_modules/*\n./.next\n.next"
  },
  {
    "path": "README.md",
    "chars": 710,
    "preview": "# guiareact.org \nSite em Português com tradução do Original reactpatterns.com de Michael Chan - [@chantastic](https://gi"
  },
  {
    "path": "components/header.js",
    "chars": 703,
    "preview": "export default function AppHeader(props){\n\n    return(\n        <header>\n            <h1>{props.title}</h1>\n            <"
  },
  {
    "path": "components/mdcontainer.js",
    "chars": 425,
    "preview": "import ReactMarkdown from \"react-markdown\";\nimport remarkSlug from \"remark-slug\";\nimport remarkLinks from \"remark-extern"
  },
  {
    "path": "components/pagehead.js",
    "chars": 1447,
    "preview": "export default function PageHead(props) {\n  const GA_TRACKING_ID = \"G-TQFVHD7RW1\";\n\n  return (\n    <>\n      <title key=\""
  },
  {
    "path": "config/md-loader.js",
    "chars": 266,
    "preview": "import Hooks from \"../documentation/DOC-HOOKS.md\";\nimport Contribua from \"../documentation/DOC-CONTRIBUA.md\";\nimport Lin"
  },
  {
    "path": "config/static-paths.js",
    "chars": 389,
    "preview": "const ROUTES = [\n  { params: { slug: \"hooks\", title: \"Guia de Hooks\" } },\n  { params: { slug: \"contribua\", title: \"Guia "
  },
  {
    "path": "documentation/DOC-HOME.md",
    "chars": 21615,
    "preview": "# Guia de Padrões React\n\nUm guia de padrões React em Português.\n\nBaseado no [Original](https://reactpatterns.com) por Mi"
  },
  {
    "path": "next.config.js",
    "chars": 155,
    "preview": "module.exports = {\n  webpack: (config) => {\n    config.module.rules.push({\n      test: /\\.md$/,\n      use: 'raw-loader',"
  },
  {
    "path": "package.json",
    "chars": 1139,
    "preview": "{\n  \"name\": \"guiareact.org\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Guia de Padrões React em Português.Baseado no React"
  },
  {
    "path": "pages/_app.js",
    "chars": 235,
    "preview": "import React from \"react\";\nimport \"highlight.js/styles/atom-one-dark-reasonable.css\";\nimport \"../styles/style.css\";\n\nfun"
  },
  {
    "path": "pages/_document.js",
    "chars": 1089,
    "preview": "import Document, { Html, Head, Main, NextScript } from \"next/document\";\nimport PageHead from \"../components/pagehead\";\ni"
  },
  {
    "path": "pages/index.js",
    "chars": 334,
    "preview": "import Markdown from \"../documentation/DOC-HOME.md\"\nimport MdContainer from \"../components/mdcontainer\"\n\n\nexport default"
  },
  {
    "path": "styles/style.css",
    "chars": 4527,
    "preview": "@import url(\"https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap\");\n\nhtml {\n  box-sizing: bord"
  }
]

About this extraction

This page contains the full source code of the rubenmarcus/guiareact.org GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 16 files (33.2 KB), approximately 9.7k tokens, and a symbol index with 11 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!