React.js: Estados e Eventos

De Aulas


Afluentes: Desenvolvimento Front-end II, Usabilidade, desenvolvimento web, mobile e jogos

State React

O objeto state é onde são armazenados valores de propriedades pertencentes ao componente. Quando modificado, há uma nova renderização do componente. Ele é inicializado no construtor.

class Car extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      brand: "Ford",
      model: "Mustang",
      color: "red",
      year: 1964
    };
  }
  render() {
    return (
      <div>
        <h1>My Car</h1>
      </div>
    );
  }
}

Podemos referenciar o objet state de qualquer lugar do componente usando this.state.nome_da_propriedade.

class Car extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      brand: "Ford",
      model: "Mustang",
      color: "red",
      year: 1964
    };
  }
  render() {
    return (
      <div>
        <h1>My {this.state.brand}</h1>
        <p>
          It is a {this.state.color}
          {this.state.model}
          from {this.state.year}.
        </p>
      </div>
    );
  }
}

Para modificar o objeto state, usamos o método this.setState().

No exemplo a seguir, um botão usa o evento onClick que modifica a propriedade da cor.

class Car extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      brand: "Ford",
      model: "Mustang",
      color: "red",
      year: 1964
    };
  }
  changeColor = () => {
    this.setState({color: "blue"});
  }
  render() {
    return (
      <div>
        <h1>My {this.state.brand}</h1>
        <p>
          It is a {this.state.color}
          {this.state.model}
          from {this.state.year}.
        </p>
        <button
          type="button"
          onClick={this.changeColor}
        >Change color</button>
      </div>
    );
  }
}

Eventos

Assim como no HTML, o React pode efetuar ações baseadas nos eventos dos usuários, tais como click, change, mouseover, etc..

No React, para adicionar um evento, colocamos o nome da função que queremos chamar entre chaves (onClick={shoot}) ao invés de chamada de função (onClick="shoot()").

Como boa prática de programação no React, é interessante colocar o tratamento do evento como um método em uma classe componente.

class Football extends React.Component {
  shoot = () => {
    alert(this);
    /*
    The 'this' keyword refers to the component object
    */
  }
  render() {
    return (
      <button onClick={this.shoot}>Take the shot!</button>
    );
  }
}

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

Observe no exemplo acima que também podemos usar o this para pegar uma função do objeto ou atibuto.

Podemos também passar parâmetros.

class Football extends React.Component {
  shoot = (a) => {
    alert(a);
  }
  render() {
    return (
      <button onClick={() => this.shoot("Goal")}>Take the shot!</button>
    );
  }
}

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

IMPORTANTE: Veja que quando passamos parâmetros usamos () => antes da função. Isso porque se colocarmos apenas

onClick={this.shot("Goal")},

o Reactjs vai executar a função imediatamente para colocar o resultado ali e pode entrar em looping, travando a aplicação. Ao colocarmos

onClick{() => this.shot("Goal")},

estamos avisando o React que estamos passando uma função anônima como parâmetro, garantindo que o React só executará quando o evento for acionado.

Eventos de Objetos React

Podemos pegar os eventos no React. No exemplo a seguir, estamos pegando o evento "click" do mouse. Veja que estamos usando a sintaxe de arrow function.

class Football extends React.Component {
  shoot = (a, b) => {
    alert(b.type);
    /*
    'b' representa o evento React que chamou a função,
    nesse caso foi o evento 'click'.
    */
  }
  render() {
    return (
      <button onClick={(ev) => this.shoot("Goal", ev)}>Take the shot!</button>
    );
  }
}

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

Sem o uso de arrow function, o objeto event do React é enviado automaticamente como um último parâmetro ao usar o método bind().

class Football extends React.Component {
  shoot = (a, b) => {
    alert(b.type);
    /*
    'b' represents the React event that triggered the function,
    in this case the 'click' event
    */
  }
  render() {
    return (
      <button onClick={this.shoot.bind(this, "Goal")}>Take the shot!</button>
    );
  }
}

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


Juntando tudo

Agora vamos trabalhar com estados e eventos para mostrar ou esconder um elemento (no caso texto) quando clicamos em um botão.

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            hidden: false,
        };
    }

    changeHidden = () => {
        let hid = !this.state.hidden;
        this.setState({ hidden: hid });
    }

    render() {
        return (
            <div>
                <h1>Esconde Texto</h1>
                <button type='button' onClick={this.changeHidden}>
                    {(this.state.hidden ? "mostrar" : "esconder")}
                </button>
                <p hidden={(this.state.hidden ? "hidden" : "")}>
                    Este é o meu texto.
                </p>
            </div>
        );
    }
}

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