Aula 12 – React – Componentes – Classes – Hooks – useEffect

Aula 12 – React – Componentes – Classes – Hooks – useEffect

Tutorial React

Tutorial React

Voltar para página principal do blog

Todas as aulas desse curso

Aula 11                        Aula 13

Meus Canais

Toti:

https://www.youtube.com/channel/UCUEtjLuDpcOvR3mIUr-viOA

Backing track / Play-along:

https://www.youtube.com/channel/UCT3TryVMqTqYBjf5g5WAHfA

Código Fluente

https://www.youtube.com/channel/UCgn-O-88XBAwdG9gUWkkb0w

Putz!

https://www.youtube.com/channel/UCZXop2-CECwyFYmHbhnAkAw

Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook

Esse é o link do código fluente no Pinterest

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Melhore seu NETWORKING

Participe de comunidades de desenvolvedores:

Fiquem a vontade para me adicionar ao linkedin.

E também para me seguir no GITHUB.

Ah, se puder, clica na estrela nos meus repositórios pra dá uma força ao meu perfil no GITHUB

Códigos da aula

Usando o hook useEffect()

https://github.com/toticavalcanti/react-hooks-usestate-example/tree/useState-hook-example

Usando classe, componentDidMount() e componentDidUpdate()

https://github.com/toticavalcanti/react-hooks-usestate-example/tree/useEffect-hook-with-class-example

Link da documentação oficial:

https://reactjs.org/tutorial/

Aula 12 – React – Componentes – Classes – Hooks – useEffect

O useEffect() é diferente do useState().

A useState() retorna um par de valores: o state atual e uma função que atualiza o state.

O que o useEffect() faz é obter uma função que é chamada sempre que o componente muda ou sempre que o componente é atualizado e renderizado novamente.

No nosso exemplo, a gente tem no card, um campo para digitar um nome.

Nós vamos fazer o seguinte teste, abri o console do navegador para ver o resultado do console.log(‘Oi’) que tá dentro do useEffect().

Em seguida, vamos digitar qualquer coisa no campo disponível do card.

Vejam que a cada letra nova, vai disparar o useEffect() e imprimir o Oi! do console.log(), porque qualquer mudança no componente que tá na tela, que tá no DOM, vai disparar o useEffect().

Isto é, cada vez que o componente é re-renderizado, ele dispara o useEffect().


useEffect( () => {
  console.log('Oi!');
});

Quando o componente for montado pela primeira vez, o useEffect() é disparado, e também, todas as vezes que mudar alguma coisa no componente, como por exemplo, você digitar uma letra a mais no campo do card, ou um backspace.

O useEffect() imita o método de ciclo de vida componentDidMount() e também qualquer um dos métodos de ciclo de vida de atualização, que disparam quando o render() é chamado.


useEffect( () => {
  console.log('Oi!');
});

Vamos ao código

O único arquivo que vamos mexer é:

src/components/use-state-component/use-state-example-component.jsx


import React, {useState, useEffect} from 'react';

import Card from '../card/card.component';

const UseEffectExample = () => {
  const [user, setUser] = useState(null);
  const [searchQuery, setSearchQuery] = useState('Bret');

  useEffect(() => {
    console.log('Disparou o userEffect()!')
  });

  return (
      <Card>
        <input 
          type='search' 
          value={searchQuery}
          onChange={event => setSearchQuery(event.target.value)}
        />
        {user? (
          <div>
            <h3>{user.name}</h3>
            <h3>{user.username}</h3>
            <h3>{user.email}</h3>
          </div>
        ) : (
            <p>Usuário não encontrado</p>
        )}
      </Card>
  );
};

export default UseEffectExample;

Veja o que acontece no console do browser, quando você digita ou deleta qualquer caractere no campo search do card.

useEffect disparando varias vezes

useEffect disparando varias vezes

E se a gente não quiser disparar o useEffect() a cada update do component?

Queremos que ele se comporte como o componentDidMount().

A forma de fazer isso é passando um segundo parâmetro para ele.

Esse segundo parâmetro será um array.

O que este array recebe são propriedades que esse useEffect() tem acesso e que irão disparar quando o componente for re-renderizado.

Então, se a gente passar [searchQuery] ele vai continuar disparando a cada mudança no campo, como no exemplo mostrado acima.

Se a gente passar [user], o useEffect() só vai disparar na primeira renderização, ou quando o estado do user mudar.

O useEffect() é um listening, isto é, um ouvinte, ele fica ouvindo as propriedades que a gente passa para ele nesse array que é o segundo parâmetro dele.

Então, quando a gente passa o searchQuery no array, ele vai ficar ouvido essa propriedade e sempre que ela mudar, o useEffect() é disparado.

Faça o teste agora passando o array para o userEffect() com o user dentro.

src/components/use-state-component/use-state-example-component.jsx


import React, {useState, useEffect} from 'react';

import Card from '../card/card.component';

const UseEffectExample = () => {
  const [user, setUser] = useState(null);
  const [searchQuery, setSearchQuery] = useState('Bret');

  useEffect(() => {
    console.log('Disparou o userEffect()!')
  }, [user]);

  return (
      <Card>
        <input 
          type='search' 
          value={searchQuery}
          onChange={event => setSearchQuery(event.target.value)}
        />
        {user? (
          <div>
            <h3>{user.name}</h3>
            <h3>{user.username}</h3>
            <h3>{user.email}</h3>
          </div>
        ) : (
            <p>Usuário não encontrado</p>
        )}
      </Card>
  );
};

export default UseEffectExample;

Veja agora que só disparou quando montou o componente no browser.

useEffect disparando uma vez só

useEffect disparando uma vez só

O userEffect() é o lugar onde vamos colocar o código assíncrono, isto é, um código que depende de outro sistema, e que leva um tempo para retornar com uma resposta de erro ou de sucesso.

No caso do nosso exemplo, é uma chamada a uma API externa(jsonplaceholder.typicode.com/users).

src/components/use-state-component/use-state-example-component.jsx


import React, {useState, useEffect} from 'react';

import Card from '../card/card.component';

const UseEffectExample = () => {
  const [user, setUser] = useState(null);
  const [searchQuery, setSearchQuery] = useState('Bret');

  useEffect(() => {
        console.log('Disparou o userEffect()!')
        const fetchData = async () => {
          const response = await fetch(`https://jsonplaceholder.typicode.com/users?username=${searchQuery}`);
          const resJson = await response.json();
          setUser(resJson);
        } 
        fetchData()
  });

  return (
      <Card>
        <input 
          type='search' 
          value={searchQuery}
          onChange={event => setSearchQuery(event.target.value)}
        />
        {user? (
          <div>
            <h3>{user.name}</h3>
            <h3>{user.username}</h3>
            <h3>{user.email}</h3>
          </div>
        ) : (
            <p>Usuário não encontrado</p>
        )}
      </Card>
  );
};

export default UseEffectExample;

Veja que a response.json() é assícrona.

Isso é porque após a fetch(), apenas os cabeçalhos foram lidos.

Portanto, para analisar o corpo como JSON, primeiro os dados do corpo devem ser lidos no fluxo de entrada.

E, como a leitura do fluxo TCP é assíncrona, a operação .json() acaba sendo assíncrona.

Observação: a análise real do JSON em si não é assíncrona, só a recuperação dos dados do fluxo de entrada que é assíncrono.

Veja o resultado no browser

useEffect disparando varias vezes com fetchData

useEffect disparando varias vezes com fetchData

Veja que ele vai ficar disparando sem parar, vai ficar em loop.

O padrão do useEffect() é ficar em loop, porque ele é um listening.

O propósito do array que é o segundo parâmetro, é pra dizer para ele ficar ouvindo só algumas propriedades que a gente passar para ele, ou nenhuma como vamos fazer no exemplo abaixo.

Então reforçando, vamos colocar um array vazio como segundo parâmetro do useEffect() para ele não ouvir nenhuma propriedade e daí, não ficar disparando o tempo todo.

src/components/use-state-component/use-state-example-component.jsx


import React, {useState, useEffect} from 'react';

import Card from '../card/card.component';

const UseEffectExample = () => {
  const [user, setUser] = useState(null);
  const [searchQuery, setSearchQuery] = useState('Bret');

  useEffect(() => {
        console.log('Disparou o userEffect()!')
        const fetchData = async () => {
          const response = await fetch(`https://jsonplaceholder.typicode.com/users?username=${searchQuery}`);
          const resJson = await response.json();
          setUser(resJson);
        } 
        fetchData()
  }, []);

  return (
      <Card>
        <input 
          type='search' 
          value={searchQuery}
          onChange={event => setSearchQuery(event.target.value)}
        />
        {user? (
          <div>
            <h3>{user.name}</h3>
            <h3>{user.username}</h3>
            <h3>{user.email}</h3>
          </div>
        ) : (
            <p>Usuário não encontrado</p>
        )}
      </Card>
  );
};

export default UseEffectExample;

Veja o resultado no browser

useEffect disparando só uma vez com fetch

useEffect disparando só uma vez com fetch

Como o userEffect() não tá escutando nada, pode mudar qualquer propriedade que ele não vai disparar.

Refatorando para pegar as mudanças da propriedade searchQuery

src/components/use-state-component/use-state-example-component.jsx


import React, {useState, useEffect} from 'react';

import Card from '../card/card.component'; 

const UseEffectExample = () => {
    const [user, setUser] = useState(null);
    const [searchQuery, setSearchQuery] = useState('Bret');
    useEffect(() => {
        'Disparou o userEffect()!'
        const fetchData = async () => {
        const response = await fetch(`https://jsonplaceholder.typicode.com/users?username=${searchQuery}`);
        const resJson = await response.json();
        setUser(resJson[0]);
    }
    fetchData()
    }, [searchQuery]);
    return (
        <Card>
            <input 
            type='search' 
            value={searchQuery}
            onChange={event => setSearchQuery(event.target.value)}
        />
        {user? (
            <div>
                <h3>{user.name}</h3>
                <h3>{user.username}</h3>
                <h3>{user.email}</h3>
            </div>
        ) : (
                <p>Usuário não encontrado</p>
            )}
        </Card>
    );
};

export default UseEffectExample;

Veja o resultado no browser

useEffect disparando com searchQuery

useEffect disparando com searchQuery

Implementação usando classes ao invés de hooks

src/components/use-state-component/use-state-example-component.jsx


import React from 'react';
import Card from '../card/card.component';

export class StateClassComponent extends React.Component {
    constructor() {
        super();
        this.state = {
            user: null,
            searchQuery: 'Bret'
        };
    }

    componentDidMount(){
        console.log('O componentDidMount() foi disparado')
        this.fetchData();
    }

    componentDidUpdate(previousProps, previousState) {
        if (previousState.searchQuery !== this.state.searchQuery) {
            console.log('O componentDidUpdatet() foi disparado')
            this.fetchData();
        }
    }

    fetchData = async () => {
        const resp = await fetch(
            `https://jsonplaceholder.typicode.com/users?username=${this.state.searchQuery}`
        );
        const resJson = await resp.json();
        this.setState({ user: resJson[0]});
    };
    /* handleChange() function to set a new state for input */
    handleInputChange = (event) => {
    //console.log(event.target.value)
    this.setState({
        searchQuery: event.target.value
    })
    }
    render() {
        return (
            <Card> 
                <input 
                    type='search' 
                    value={this.state.searchQuery} 
                    onChange={(e) => this.handleInputChange(e)} 
                /> 
                {this.state.user ? ( 
                <div> 
                    <h3>{this.state.user.name}</h3> 
                    <h3>{this.state.user.username}</h3> 
                    <h3>{this.state.user.email}</h3> 
                </div> 
                ) : ( 
                <p>Usuário não encontrado</p> 
                )}
            </Card>
        );
    }
}

export default StateClassComponent;

Veja o resultado no browser

O resultado é exatamente o mesmo.

Ficamos por aqui, até a próxima.  😉

Aula 11                        Aula 13

Todas as aulas desse curso

Voltar para página principal do blog

Toti:

https://www.youtube.com/channel/UCUEtjLuDpcOvR3mIUr-viOA

Backing track / Play-along:

https://www.youtube.com/channel/UCT3TryVMqTqYBjf5g5WAHfA

Código Fluente

https://www.youtube.com/channel/UCgn-O-88XBAwdG9gUWkkb0w

Putz!

https://www.youtube.com/channel/UCZXop2-CECwyFYmHbhnAkAw

Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook

Esse é o link do código fluente no Pinterest

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Códigos da aula

Códigos da aula

Usando o hook useEffect()

https://github.com/toticavalcanti/react-hooks-usestate-example/tree/useState-hook-example

Usando classe, componentDidMount() e componentDidUpdate()

https://github.com/toticavalcanti/react-hooks-usestate-example/tree/useEffect-hook-with-class-example

Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook

Link do código fluente no Pinterest

Obrigado, até a próxima e bons estudos. 😉

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>