Edit on GitHub

Componentes e propriedades

Componentes permitem você quebrar a interface de usuário em peças independentes, reusáveis e pensar em cada peça isoladamente.

Conceitualmente, componentes são como funções JavaScript. Eles aceitam entradas arbitrárias(chamadas de "props") e retornam elementos React descrevendo o que deve aparecer na tela.

Componentes funcionais e classes #

A maneira mais simples de definir um componente é escrever uma função JavaScript:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

Esta função é um componente React válido porque aceita um único objeto "props" como argumento com dados e retorna um elemento React. Nós chamamos esses componentes de "funcional" porque eles são literalmente funções JavaScript.

Você também podemos usar uma classe ES6 para definir um componente:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Os dois componentes acima são equivalentes do ponto de vista do React.

Classes tem alguns recursos adicionais que iremos discutir nas próximas seções. Até lá, iremos utilizar componentes funcionais para sua concisão.

Renderizando um componente #

Anteriormente, só encontramos elementos React que representam tags DOM:

const element = <div />;

No entanto, elementos também podem representar componentes definidos pelo usuário.

const element = <Welcome name="Sara" />;

Quando o React vê um elemento que representa um componente definido pelo usuário, ele passa os atributos JSX para este componente como um objeto único. Nós chamamos esse objeto de "props";

Por exemplo, este códito renderiza "Hello, Sara" na página:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

Teste este código no CodePen.

Vamos recapitular o que acontece neste exemplo:

  1. Nós chamamos ReactDOM.render() com o elemento <Welcome name="Sara" />.
  2. React chama o componente Welcome com {name: 'Sara'} como o props.
  3. Nosso componente Welcome retorna um elemento <h1>Hello, Sara</h1> como resultado.
  4. React DOM eficientemente atualizar o DOM para <h1>Hello, Sara</h1>.

Caveat:

Sempre inicie os nomes dos componente com uma letra maiúscula.

Por exemplo, <div /> representa uma tag DOM, mas <Welcome /> representa um componente e requer que Welcome esteja no escopo.

Criando componentes #

Componentes podem se referir a outros componentes em suas saídas. Isso nos permite usar a mesma abstração do componente em qualquer nível de detalhes. Um botão, um form, uma caixa de diálogo, uma tela: em aplicações React, todos são comumente expressos como componentes.

Por exemplo, nós podemos criar um componente App que renderiza Welcome várias vezes:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

Teste este código no CodePen.

Tipicamente, novas aplicações React tem um único componente App no topo. No entanto, se você integrar React a uma aplicação existente, você poderia começar de baixo para cima com um pequeno componente como um Button e gradativamente trabalhar seu caminho para o topo da hierarquia da view.

Caveat:

Componentes devem retornar um único elemento root. É por isso que adicionamos uma <div> para conter todos os elementos de <Welcome />.

Extraindo componentes #

Não tenha medo de separar componentes em componentes menores.

Por exemplo, considere este componentes Comment:

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

Teste este código no CodePen.

Ele aceita author (um objeto), text (uma string), e date (uma data) como propriedades e descreve um comentário numa rede social.

Esse componente pode ser complicado para alterar devido a todos os subcomponentes e pode ser difícil de reusar partes dele. Vamos extrair alguns componentes desse componente.

Primeiro vamos extrair Avatar:

function Avatar(props) {
  return (
    <img className="Avatar"
      src={props.user.avatarUrl}
      alt={props.user.name}
    />
  );
}

O Avatar não precisa saber the é renderizado dentro de Comment. Isso é porque nós demos a ele um nome de propriedade mais genérico: user em vez de author.

Nós recomendamos nomear propriedades a partir do ponto de vista do componente em vez de o contexto no qual ele está sendo usado.

Podemos simplificar Comment mais um pouco:

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <Avatar user={props.author} />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

A seguir, vamos extrair um componente UserInfo que renderiza um Avatar próximo ao nome do usuário:

function UserInfo(props) {
  return (
    <div className="UserInfo">
      <Avatar user={props.user} />
      <div className="UserInfo-name">
        {props.user.name}
      </div>
    </div>
  );
}

Isso nos faz simplificar Comment ainda mais:

function Comment(props) {
  return (
    <div className="Comment">
      <UserInfo user={props.author} />
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

Teste este código no CodePen.

Extrair componentes pode ser uma trabalho pesado no início, mas ter uma paleta de componentes reusáveis compensa em aplicações grandes. Uma boa regra de outro é se uma parte da sua interface de usuário é utilizada várias vezes (Button, Panel, Avatar), ou é bastante complexa por si só (App, FeedStory, Comment), é uma boa condidata para ser um componente reutilizável.

Props são somente leitura #

Se você declara um componente como uma função ou uma classe, ele nunca deve modificar suas propriedades. Considerem a função sum:

function sum(a, b) {
  return a + b;
}

Tais funções são chamadas "pure" porque elas não tentam alterar suas entradas, e sempre retornar o mesmo resultado para as mesmas entradas.

Em contrapartida, esta função é impura porque ela muda suas entradas:

function withdraw(account, amount) {
  account.total -= amount;
}

React é bastante flexível mas tem uma única regra estrita:

Todos os componentes React devem agir como funções puras com respeito a suas propriedades

Claro, interfaces de usuários das aplicações são dinâmicas e mudam todo tempo. Na próxima seção, nós iremos introduzir um novo conceito de "state"(estado). State(estado) permite a componentes React mudar suas saídas ao longo do tempo em resposta as ações do usuário, respostas de rede, e qualquer outra coisa, sem violar esta regra.