Aula 12 - React - Componentes - Classes - Hooks - useEffect
Meus Canais
Toti:
Backing track / Play-along:
Código Fluente
Putz!
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:
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()
Usando classe, componentDidMount() e componentDidUpdate()
Link da documentação oficial:
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.
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.
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
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
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
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. ;)
Toti:
Backing track / Play-along:
Código Fluente
Putz!
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:
Códigos da aula
Códigos da aula
Usando o hook useEffect()
Usando classe, componentDidMount() e componentDidUpdate()
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. ;)