Você escreveu vários componentes usando 
ganchos . Talvez - eles até criaram um pequeno aplicativo. Em geral, você está bastante satisfeito com o resultado. Você está acostumado à API e, no processo, encontrou alguns truques úteis inesperados. Você até criou alguns de 
seus próprios ganchos e reduziu seu código para 300 linhas, colocando neles o que era representado anteriormente pela repetição de fragmentos de programa. O que você fez, você mostrou colegas. "Muito bem", disseram eles sobre o seu projeto.

Mas, às vezes, quando você usa o 
useEffect , os componentes dos mecanismos do software não se encaixam muito bem. Parece que você está perdendo alguma coisa. Tudo isso é semelhante a trabalhar com eventos de ciclo de vida de componentes com base em classe ... mas é realmente assim? 
Tentando entender o que exatamente não combina com você, você percebe que está fazendo as seguintes perguntas:
- Como jogar componentDidMountusandouseEffect?
- Como carregar dados dentro do useEffect? O que é[]?
- As funções precisam ser especificadas como dependências de efeito?
- Por que um programa às vezes acaba em um loop infinito de recarga de dados?
- Por que o estado antigo às vezes é visível dentro dos efeitos ou são encontradas propriedades antigas?
Quando comecei a usar ganchos, essas perguntas também me atormentaram. Mesmo quando eu estava preparando a documentação, não podia dizer que domino perfeitamente algumas das sutilezas. Desde então, tive vários momentos em que, de repente, percebendo algo importante, eu realmente queria exclamar: "Eureka!" Sobre o que percebi nesses momentos, quero lhe contar. O que você aprendeu sobre o 
useEffect agora permitirá que você veja claramente as respostas óbvias às perguntas acima.
Mas, para ver as respostas a essas perguntas, precisamos primeiro dar um passo atrás. O objetivo deste artigo não é fornecer aos leitores instruções passo a passo para trabalhar com o 
useEffect . Ele visa ajudá-lo, por assim 
useEffect " 
useEffect " o 
useEffect . E, francamente, não há muito o que aprender. De fato, na maior parte do tempo, gastamos esquecendo o que sabíamos antes.
Tudo na minha cabeça se uniu somente depois que parei de olhar para o gancho 
useEffect através do prisma dos métodos familiares do ciclo de vida dos componentes baseados em componentes.
"Você deve esquecer o que foi ensinado"
habr.com/ru/company/ruvds/blog/445276/YodaSupõe-se que o leitor deste material esteja familiarizado com a API 
useEffect . Este é um artigo bastante longo, que pode ser comparado com um pequeno livro. O fato é que prefiro expressar meus pensamentos dessa maneira. Abaixo, muito brevemente, são dadas respostas para as perguntas que foram discutidas acima. Talvez sejam úteis para aqueles que não têm tempo ou desejam ler todo o material.
Se o formato em que vamos considerar o 
useEffect , com todas as suas explicações e exemplos, não for muito adequado para você, aguarde um pouco - até o momento em que essas explicações aparecerem em inúmeros outros manuais. Aqui está a mesma história que a própria biblioteca do React, que em 2013 era algo completamente novo. Leva algum tempo para que a comunidade de desenvolvimento reconheça o novo modelo mental e apareça o material educacional baseado nesse modelo.
Respostas às perguntas
Aqui estão respostas curtas para as perguntas feitas no início deste material, destinadas a quem não deseja ler todo o texto. Se, ao ler essas respostas, você sentir que realmente não entende o significado do que lê, examine o material. Você encontrará explicações detalhadas no texto. Se você está lendo tudo, pode pular esta seção.
PlayComo reproduzir componentDidMount usando useEffect?
Embora você possa usar a construção 
useEffect(fn, []) para reproduzir a funcionalidade 
componentDidMount , ela não é o equivalente exato de 
componentDidMount . Ou seja, ao contrário de 
componentDidMount , captura propriedades e estado. Portanto, mesmo dentro do retorno de chamada, você verá as propriedades e o estado iniciais. Se você quiser ver a versão mais recente de algo, escreva-a no link 
ref . Mas geralmente há uma maneira mais simples de estruturar o código, portanto, isso é opcional. Lembre-se de que o modelo de efeitos mentais é diferente daquele aplicável ao 
componentDidMount e a outros métodos de ciclo de vida do componente. Portanto, tentar encontrar os equivalentes exatos pode fazer mais mal do que bem. Para trabalhar produtivamente, você precisa, por assim dizer, "pensar em efeitos". A base de seu modelo mental está mais próxima da implementação da sincronização do que de responder a eventos no ciclo de vida dos componentes.
LoadComo carregar corretamente os dados no useEffect? O que é []?
Aqui está um bom guia para carregar dados usando 
useEffect . Tente ler na íntegra! Não é tão grande quanto isso. Os colchetes, 
[] , representando uma matriz vazia, significam que o efeito não usa os valores que participam do fluxo de dados React e, por esse motivo, seu uso único pode ser considerado seguro. Além disso, o uso de uma matriz vazia de dependências é uma fonte comum de erros no caso de um determinado valor ser realmente usado no efeito. Você precisará dominar várias estratégias (principalmente apresentadas na forma de 
useReducer e 
useCallback ) que podem ajudar a eliminar a necessidade de uma dependência, em vez de descartá-la de maneira irracional.
Functions As funções precisam ser especificadas como dependências de efeito?
Recomenda-se que as funções que não precisam de propriedades ou de um estado sejam tomadas fora dos componentes e que as funções usadas apenas pelos efeitos sejam colocadas dentro dos efeitos. Se depois disso, seu efeito ainda usar funções que estão no escopo da renderização (incluindo funções das propriedades), envolva-as em 
useCallback onde elas são declaradas e tente usá-las novamente. Por que isso é importante? As funções podem "ver" os valores das propriedades e do estado, para que participem do fluxo de dados. 
Aqui estão informações mais detalhadas sobre isso em nossas Perguntas frequentes.
▍ Por que um programa às vezes acaba em um loop infinito de recarga de dados?
Isso pode acontecer quando o carregamento de dados é realizado em um efeito que não possui um segundo argumento representando as dependências. Sem ele, os efeitos são executados após cada operação de renderização - o que significa que definir o estado fará com que esses efeitos sejam recuperados. Um loop infinito também pode ocorrer se um valor que sempre muda for indicado na matriz de dependências. Descubra que tipo de valor é possível removendo dependências uma por vez. No entanto, remover dependências (ou imprudentemente usar 
[] ) geralmente é a abordagem errada para resolver um problema. Em vez disso, você deve encontrar a fonte do problema e realmente resolvê-lo. Por exemplo, funções podem causar um problema semelhante. Você pode ajudar a resolvê-lo colocando-os em efeito, movendo-os para fora dos componentes ou 
useCallback em 
useCallback . Para evitar a criação de vários objetos, você pode usar 
useMemo .
▍ Por que às vezes o estado antigo é visível dentro dos efeitos ou são encontradas propriedades antigas?
Os efeitos sempre “veem” as propriedades e o estado da renderização em que são declarados. Isso ajuda a 
evitar erros , mas em alguns casos, pode interferir na operação normal do componente. Nesses casos, você pode usar links de 
ref mutável explicitamente para trabalhar com esses valores (você pode ler sobre isso no final do artigo mencionado acima). Se você acha que vê propriedades ou estado a partir da renderização antiga, mas não espera isso, pode ter perdido algumas dependências. Para aprender a vê-los, use 
esta regra do linter. Em alguns dias, isso se tornará algo como sua segunda natureza. Além disso, dê uma olhada 
nesta resposta em nossas Perguntas frequentes.
Espero que essas respostas às perguntas tenham sido úteis para quem as lê. Agora vamos falar mais sobre 
useEffect .
Cada renderização possui suas próprias propriedades e estado.
Antes de podermos discutir os efeitos, precisamos falar sobre renderização.
Aqui está o componente do contador funcional.
 function Counter() { const [count, setCount] = useState(0); return (   <div>     <p>You clicked {count} times</p>     <button onClick={() => setCount(count + 1)}>       Click me     </button>   </div> ); } 
Dê uma olhada na 
<p>You clicked {count} times</p> . O que ela quer dizer? A constante constante de alguma forma "observa" as mudanças no estado e é atualizada automaticamente? Essa conclusão pode ser considerada uma espécie de primeira ideia valiosa de alguém que está estudando o React, mas não é um 
modelo mental preciso do que está acontecendo.
No nosso exemplo, 
count é apenas um número. Isso não é algum tipo de "ligação de dados" mágica, não é algum tipo de "objeto observador" ou "proxy", ou qualquer outra coisa. À nossa frente está um bom número antigo, assim:
 const count = 42;  
Durante a saída do primeiro componente, o valor da 
count obtido de 
useState() é 0. Quando chamamos 
setCount(1) , o React chama o componente novamente. Essa 
count tempo será 1. E assim por diante:
 
React chama o componente sempre que atualizarmos o estado. Como resultado, cada operação de renderização “vê” seu próprio valor do estado do 
counter , que, dentro da função, é uma constante.
Como resultado, esta linha não executa nenhuma operação especial de ligação de dados:
 <p>You clicked {count} times</p> 
Ele incorpora apenas um valor numérico no código gerado durante a renderização. Este número é fornecido pelo React. Quando chamamos 
setCount , o React chama o componente novamente com um valor de 
count diferente. O React atualiza o DOM para que o modelo de objeto do documento corresponda à saída de dados mais recente durante a renderização do componente.
A conclusão mais importante que se pode tirar disso é que a 
count é uma constante dentro de qualquer renderização específica e não muda com o tempo. O componente que é chamado repetidamente muda. Cada renderização "vê" seu próprio valor de 
count , que é isolado para cada uma das operações de renderização.
Neste material, você pode encontrar detalhes sobre esse processo.
Cada renderização possui seus próprios manipuladores de eventos.
Tudo ainda está claro. E os manipuladores de eventos?
Dê uma olhada neste exemplo. Aqui, três segundos depois de clicar no botão, uma caixa de mensagem é exibida com informações sobre o valor armazenado na 
count :
 function Counter() { const [count, setCount] = useState(0); function handleAlertClick() {   setTimeout(() => {     alert('You clicked on: ' + count);   }, 3000); } return (   <div>     <p>You clicked {count} times</p>     <button onClick={() => setCount(count + 1)}>       Click me     </button>     <button onClick={handleAlertClick}>       Show alert     </button>   </div> ); } 
Suponha que eu execute a seguinte sequência de ações:
- Trarei o valor da countpara 3 clicando no botãoClick me.
- Clique no botão Show alert.
- Aumente o valor para 5 antes que o tempo limite expire.
Aumentando o valor da contagem depois de clicar no botão Mostrar alertaO que você acha que aparece na caixa de mensagem? Será exibido 5 lá, que corresponde ao valor da 
count no momento em que o timer foi acionado, ou 3 - ou seja, o valor da 
count no momento em que o botão for pressionado?
Agora você encontrará a resposta para esta pergunta, mas se quiser descobrir tudo sozinho - 
aqui está uma versão funcional deste exemplo.
Se o que você viu lhe parece incompreensível - aqui está um exemplo mais próximo da realidade. Imagine um aplicativo de bate-papo no qual, no estado, o 
ID destinatário atual da mensagem esteja armazenado e haja um botão 
Send . 
Neste material, o que está acontecendo é considerado em detalhes. De fato, a resposta correta para a pergunta do que aparece na caixa de mensagem é 3.
O mecanismo para exibir uma caixa de mensagem "capturou" o estado no momento em que o botão foi clicado.
Existem maneiras de implementar outra versão do comportamento, mas, por enquanto, trataremos do comportamento padrão do sistema. Ao construir modelos mentais de tecnologias, é importante distinguir o "caminho de menor resistência" de todos os tipos de "saídas de emergência".
Como tudo isso funciona?
Já dissemos que o valor da 
count é uma constante para cada chamada específica à nossa função. Eu acho que vale a pena pensar nisso com mais detalhes. O ponto é que nossa função é chamada várias vezes (uma vez para cada operação de renderização), mas com cada uma dessas chamadas, a 
count interna é uma constante. Essa constante é configurada para algum valor específico (representando o estado de uma operação de renderização específica).
Esse comportamento das funções não é algo especial para o React - as funções comuns se comportam de maneira semelhante:
 function sayHi(person) { const name = person.name; setTimeout(() => {   alert('Hello, ' + name); }, 3000); } let someone = {name: 'Dan'}; sayHi(someone); someone = {name: 'Yuzhi'}; sayHi(someone); someone = {name: 'Dominic'}; sayHi(someone); 
Neste exemplo, a variável externa 
someone reatribuída várias vezes. A mesma coisa pode acontecer em algum lugar dentro do React, o estado atual do componente pode mudar. No entanto, dentro da função 
sayHi , há um 
name constante local associado à 
person de uma chamada específica. Esta constante é local, portanto, seus valores em diferentes chamadas de função são isolados um do outro! Como resultado, após um tempo limite, cada janela de mensagem exibida “lembra” seu próprio valor de 
name .
Isso explica como nosso manipulador de eventos captura o valor da 
count quando um botão é clicado. Se nós, trabalhando com componentes, aplicamos o mesmo princípio, acontece que cada renderização "vê" seu próprio valor de 
count :
 
Como resultado, cada renderização, de fato, retorna sua própria "versão" 
handleAlertClick . Cada uma dessas versões "lembra" seu próprio valor de 
count :
 
É por 
isso que , 
neste exemplo, os manipuladores de eventos "pertencem" a renderizações específicas e, quando você clica no botão, o componente usa o estado de 
count dessas renderizações.
Dentro de cada renderização específica, as propriedades e o estado sempre permanecem os mesmos. Mas se diferentes operações de renderização usarem suas próprias propriedades e estado, o mesmo acontecerá com qualquer mecanismo que as utilize (incluindo manipuladores de eventos). Eles também "pertencem" a renderizações específicas. Portanto, mesmo funções assíncronas dentro de manipuladores de eventos “verão” os mesmos valores de 
count .
Deve-se notar que, no exemplo acima, eu 
handleAlertClick os valores de 
count específicos diretamente na função 
handleAlertClick . Essa substituição "mental" não nos prejudicará, pois a 
count constante não pode ser alterada dentro de uma renderização específica. Em primeiro lugar, é uma constante e, em segundo lugar, é um número. Podemos dizer com confiança que também se pode pensar em outros significados, como objetos, mas apenas se aceitarmos como regra não fazer alterações (mutações) do estado. Ao mesmo tempo, estamos satisfeitos com a chamada para 
setSomething(newObj) com um novo objeto, em vez de alterar o existente, pois, com essa abordagem, o estado pertencente à renderização anterior permanece intocado.
Cada renderização tem seus próprios efeitos.
Esse material, como você sabe, é dedicado aos efeitos, mas ainda nem falamos sobre eles. Agora vamos consertar isso. Como se vê, trabalhar com efeitos não é particularmente diferente do que já descobrimos.
Considere 
um exemplo da documentação, que é muito semelhante ao que já analisamos:
 function Counter() { const [count, setCount] = useState(0); useEffect(() => {   document.title = `You clicked ${count} times`; }); return (   <div>     <p>You clicked {count} times</p>     <button onClick={() => setCount(count + 1)}>       Click me     </button>   </div> ); } 
Agora eu tenho uma pergunta para você. Como um efeito lê o valor mais recente da 
count ?
Talvez alguma "ligação de dados" seja usada aqui, ou um "objeto observador" que atualize o valor da 
count dentro da função de efeito? Talvez 
count seja uma variável mutável cujo valor React defina dentro de nosso componente, como resultado do qual o efeito sempre vê sua versão mais recente?
Não.
Já sabemos que, na renderização de um componente em particular, a 
count é uma constante. Até os manipuladores de eventos "veem" o valor da 
count da renderização à qual eles "pertencem" devido ao fato de que a 
count é uma constante localizada em um determinado escopo. O mesmo vale para efeitos!
E deve-se notar que essa não é a 
count variáveis 
count que de alguma forma muda dentro do efeito "inalterado". À nossa frente está a função do próprio efeito, que é diferente em cada operação de renderização.
Cada versão "vê" o valor da 
count da renderização à qual "pertence":
 
React , DOM .
, ( ), , , , «» , «».
, , .
, ( , 
). , , , .
, , :
React:
:
- : <p>You clicked 0 times</p>.
- , , : () => { document.title = 'You clicked 0 times' }.
React:
:
React:
- , , .
- () => { document.title = 'You clicked 0 times' }.
, . , , - :
:
React:
:
- : <p>You clicked 1 times</p>.
- , , : () => { document.title = 'You clicked 1 times' }.
React:
:
React:
- , , .
- () => { document.title = 'You clicked 1 times' }.
…
, , , , «» .
. :
 function Counter() { const [count, setCount] = useState(0); useEffect(() => {   setTimeout(() => {     console.log(`You clicked ${count} times`);   }, 3000); }); return (   <div>     <p>You clicked {count} times</p>     <button onClick={() => setCount(count + 1)}>       Click me     </button>   </div> ); } 
, ?
, . , , , . ! , , , , , 
count . 
.
: «, ! ?».
, , 
this.setState , , . , , 
, , , :
   componentDidUpdate() {   setTimeout(() => {     console.log(`You clicked ${this.state.count} times`);   }, 3000); } 
, 
this.state.count count , , . , , , 5 , 5 .
, JavaScript-, , , 
, , 
setTimeout , . , (React 
this.state , ), .
— , , «» , . , , , . , , . , , , , , , 
.
, ( , , - API ) , .
:
 function Example(props) { useEffect(() => {   setTimeout(() => {     console.log(props.counter);   }, 1000); });  
, «» . ! . , .
, , - , , , , . , 
ref , 
.
, , , , , . , ( ), «» React-. , , . , .
, , , :
 function Example() { const [count, setCount] = useState(0); const latestCount = useRef(count); useEffect(() => {    
- React . React 
this.state . , , 
latestCount.current . , . , , , .
?
, . , , «» .
:
 useEffect(() => {   ChatAPI.subscribeToFriendStatus(props.id, handleStatusChange);   return () => {     ChatAPI.unsubscribeFromFriendStatus(props.id, handleStatusChange);   }; }); 
, 
props — 
{id: 10} , 
{id: 20} — . , :
- React {id: 10}.
- React {id: 20}.
- React {id: 20}.
( , , .)
, «» - , , «» - , . — , , , . .
React 
, . , . . . :
- React {id: 20}.
- . {id: 20}.
- React {id: 10}.
- React {id: 20}.
, «» 
props , 
{id: 10} , , 
props {id: 20} .
, …
— ?: « ( , , - API ) , ».
! « » , . , , :
 
, , … , «» , -, 
{id: 10} .
React . , , . 
props , .
,
React , . 
.
, :
 function Greeting({ name }) { return (   <h1 className="Greeting">     Hello, {name}   </h1> ); } 
, 
<Greeting name="Dan" /> , — 
<Greeting name="Yuzhi" /> , 
<Greeting name="Yuzhi" /> . 
Hello, Yuzhi .
, , . React, . , , . 
$.addClass $.removeClass jQuery- ( — , «»), , CSS- React ( — , «»).
React DOM , . «» «».
. 
useEffect , React, .
 function Greeting({ name }) { useEffect(() => {   document.title = 'Hello, ' + name; }); return (   <h1 className="Greeting">     Hello, {name}   </h1> ); } 
useEffect , , . , - , ! , «», «».
, 
A , 
B , — 
C , , 
C . (, - ), .
, , , . ( ).
?
React
React DOM. DOM , React DOM, - .
, :
 <h1 className="Greeting"> Hello, Dan </h1> 
:
 <h1 className="Greeting"> Hello, Yuzhi </h1> 
React :
 const oldProps = {className: 'Greeting', children: 'Hello, Dan'}; const newProps = {className: 'Greeting', children: 'Hello, Yuzhi'}; 
React , 
children , DOM. , 
className . :
 domNode.innerText = 'Hello, Yuzhi';  
- ? , , .
, , - :
 function Greeting({ name }) { const [counter, setCounter] = useState(0); useEffect(() => {   document.title = 'Hello, ' + name; }); return (   <h1 className="Greeting">     Hello, {name}     <button onClick={() => setCounter(counter + 1)}>       Increment     </button>   </h1> ); } 
counter . 
document.title name , 
name . 
document.title counter , .
React … ?
 let oldEffect = () => { document.title = 'Hello, Dan'; }; let newEffect = () => { document.title = 'Hello, Dan'; };  
— . React , , . ( . 
name .)
, , ( 
deps ), 
useEffect :
   useEffect(() => {   document.title = 'Hello, ' + name; }, [name]);  
, React: «, , , , 
name ».
, , React :
 const oldEffect = () => { document.title = 'Hello, Dan'; }; const oldDeps = ['Dan']; const newEffect = () => { document.title = 'Hello, Dan'; }; const newDeps = ['Dan'];  
, , ! - - .
React
React — . , , , , 
useEffect , , , . ( !)
 function SearchResults() { async function fetchData() {    
FAQ , . .
« !», — . : , , . , , , — , .
, , . , , , , . , . .
, , .
, React
, , React , .
   useEffect(() => {   document.title = 'Hello, ' + name; }, [name]); 
—, , , 
[] , , , , :
   useEffect(() => {   document.title = 'Hello, ' + name; }, []);  
—. , «» , , .
, , , . , : « 
setInterval clearInterval ». 
. , , , 
useEffect , , , 
[] . - , ?
 function Counter() { const [count, setCount] = useState(0); useEffect(() => {   const id = setInterval(() => {     setCount(count + 1);   }, 1000);   return () => clearInterval(id); }, []); return <h1>{count}</h1>; } 
, , 
.
, « , », . , , , 
setInterval , . , ?
, — React , , . , 
count , React , , , . — .
count 0. 
setCount(count + 1) setCount(0 + 1) . , — 
[] , 
setCount(0 + 1) :
 
React, , , — .
count — , ( ):
   const count =  
. React .
,. , , React , , . — 
- .
React , . , , , .
, , , . 
count :
 useEffect(() => { const id = setInterval(() => {   setCount(count + 1); }, 1000); return () => clearInterval(id); }, [count]); 
. , , — , . 
count , 
count , 
setCount(count + 1) :
 
, 
setInterval , 
count , . , .
,, , , . — , .
.
, 
count .
 useEffect(() => {   const id = setInterval(() => {     setCount(count + 1);   }, 1000);   return () => clearInterval(id); }, [count]); 
, , 
count . , 
count setCount . , , 
count . , , 
setState :
   useEffect(() => {   const id = setInterval(() => {     setCount(c => c + 1);   }, 1000);   return () => clearInterval(id); }, []); 
« ». , 
count - , 
setCount(count + 1) . 
count - , 
count + 1 «» React. React 
count . , React — , , , .
setCount(c => c + 1) . « React », , . « » , , 
.
, , , . React. 
count :
,.
, 
setInterval , , 
c => c + 1 . 
count . React .
Google Docs
, , — ? , , «», , . , Google Docs . . , .
, . . , 
setCount(c => c + 1) , , 
setCount(count + 1) , «» 
count . , ( — «»). « React» — 
. .
( ) , Google Docs 
. — , React . , , ( , , ) .
, 
setCount(c => c + 1) , . , . , , , , , . 
setCount(c => c + 1) . 
useReducer .
, : 
count step . 
setInterval , 
step :
 function Counter() { const [count, setCount] = useState(0); const [step, setStep] = useState(1); useEffect(() => {   const id = setInterval(() => {     setCount(c => c + step);   }, 1000);   return () => clearInterval(id); }, [step]); return (   <>     <h1>{count}</h1>     <input value={step} onChange={e => setStep(Number(e.target.value))} />   </> ); } 
.
, React . 
step , . .
: 
step setInterval — 
step . , , , ! , , , , , .
, , , 
setInterval , 
step . 
step ?
, , 
useReducer .
, 
setSomething(something => ...) , , . «», , , .
step dispatch :
 const [state, dispatch] = useReducer(reducer, initialState); const { count, step } = state; useEffect(() => { const id = setInterval(() => {   dispatch({ type: 'tick' });  
.
: « , ?». , React , 
dispatch . .
!
( 
dispatch setstate useRef , React , . — .)
, , , , . 
step . , . , . :
 const initialState = { count: 0, step: 1, }; function reducer(state, action) { const { count, step } = state; if (action.type === 'tick') {   return { count: count + step, step }; } else if (action.type === 'step') {   return { count, step: action.step }; } else {   throw new Error(); } } 
, , , .
useReducer — -
, , , . , , ? , , API 
<Counter step={1} /> . , 
props.step ?
, ! , :
 function Counter({ step }) { const [count, dispatch] = useReducer(reducer, 0); function reducer(state, action) {   if (action.type === 'tick') {     return state + step;   } else {     throw new Error();   } } useEffect(() => {   const id = setInterval(() => {     dispatch({ type: 'tick' });   }, 1000);   return () => clearInterval(id); }, [dispatch]); return <h1>{count}</h1>; } 
, . , , , , . 
.
dispatch . , , . .
, , . «» , , ? , 
dispatch , React . . .
useReducer «-» . , . , , , , .
, - , .
, , , :
 function SearchResults() { const [data, setData] = useState({ hits: [] }); async function fetchData() {   const result = await axios(     'https://hn.algolia.com/api/v1/search?query=react',   );   setData(result.data); } useEffect(() => {   fetchData(); }, []);  
, .
, , . , , , , , , , , .
, , , , :
 function SearchResults() {  
, , :
 function SearchResults() { const [query, setQuery] = useState('react');  
, (, ), . .
, . , :
 function SearchResults() {  
.
? , « ». React, - .
getFetchUrl , 
query , , , , . — , 
query :
 function SearchResults() { const [query, setQuery] = useState('react'); useEffect(() => {   function getFetchUrl() {     return 'https://hn.algolia.com/api/v1/search?query=' + query;   }   async function fetchData() {     const result = await axios(getFetchUrl());     setData(result.data);   }   fetchData(); }, [query]);  
.
, « React». 
query . , , , , . , , .
exhaustive-deps eslint-plugin-react-hooks , . , , .
.
, ?
. , , . , , .
? , . : React . . , « ». , , . , , , !
, , . , 
getFetchUrl :
 function SearchResults() { function getFetchUrl(query) {   return 'https://hn.algolia.com/api/v1/search?query=' + query; } useEffect(() => {   const url = getFetchUrl('react');    
getFetchUrl — , .
, «» , . 
getFetchUrl (, , ), :
 function SearchResults() {  
, 
getFetchUrl . , — . - , , . , , , .
— .
, , :
 
, . , , .
. , 
useCallback :
 function SearchResults() {  
useCallback . : , -, , , .
, . ( 
'react' 'redux' ). , , , 
query . , , 
query , 
getFetchUrl .
, 
query useCallback :
 function SearchResults() { const [query, setQuery] = useState('react'); const getFetchUrl = useCallback(() => {  
useCallback query , , 
getFetchUrl , 
query :
 function SearchResults() { const [query, setQuery] = useState('react');  
useCallback , 
query , 
getFetchUrl , , . 
query , 
getFetchUrl , . Excel: - , , , .
— , . , :
 function Parent() { const [query, setQuery] = useState('react');  
fetchData Parent query , 
Child , .
?
, , , , . , , , , :
 class Parent extends Component { state = {   query: 'react' }; fetchData = () => {   const url = 'https://hn.algolia.com/api/v1/search?query=' + this.state.query;    
, : « , , , 
useEffect — 
componentDidMount componentDidUpdate . !». 
componentDidUpdate :
 class Child extends Component { state = {   data: null }; componentDidMount() {   this.props.fetchData(); } componentDidUpdate(prevProps) {    
, 
fetchData — ! (, , , .) - , . 
this.props.fetchData prevProps.fetchData . , , ?
   componentDidUpdate(prevProps) {   this.props.fetchData(); } 
. . ( .) , 
fetchData this.state.query ?
   render() {   return <Child fetchData={this.fetchData.bind(this, this.state.query)} />; } 
this.props.fetchData !== prevProps.fetchData true , , 
query ! .
, , , 
query Child . , , 
query , 
query :
 class Parent extends Component { state = {   query: 'react' }; fetchData = () => {   const url = 'https://hn.algolia.com/api/v1/search?query=' + this.state.query;    
, , - , , .
, , . 
this , . , , , , - . , 
this.props.fetchData , , , , , .
- 
useCallback . , , , . , . 
useCallback props.fetchData .
, 
useMemo :
 function ColorPicker() {  
, 
useCallback , - . « », , , . , . , 
.
, 
fetchData ( ), . , , . (« 
props.onComplete , ?») , .
, :
 class Article extends Component { state = {   article: null }; componentDidMount() {   this.fetchData(this.props.id); } async fetchData(id) {   const article = await API.fetchArticle(id);   this.setState({ article }); }  
, , , . . — , :
 class Article extends Component { state = {   article: null }; componentDidMount() {   this.fetchData(this.props.id); } componentDidUpdate(prevProps) {   if (prevProps.id !== this.props.id) {     this.fetchData(this.props.id);   } } async fetchData(id) {   const article = await API.fetchArticle(id);   this.setState({ article }); }  
, , , . , . , 
{id: 10} , 
{id: 20} , , . , , , . E isso está errado.
, , . — , , 
async/await ( , - ) , ( , ).
, 
async -. (, , , , .)
, , ! .
, :
 function Article({ id }) { const [article, setArticle] = useState(null); useEffect(() => {   let didCancel = false;   async function fetchData() {     const article = await API.fetchArticle(id);     if (!didCancel) {       setArticle(article);     }   }   fetchData();   return () => {     didCancel = true;   }; }, [id]);  
, , , . , .
, , , , , . , , , . . — .
useEffect , , , . React. , 
useEffect .
, , « », . . , , , , «» , .
, 
useEffect , . — . — , , — , . , , , , API.
, , 
useFetch , , 
useTheme , . , , 
useEffect . , , , .
, , 
useEffect . — , . , . ?
Suspense React , , - ( : , , ) .
Suspense , , 
useEffect , , , - . , , , . , , 
, , .
Sumário
, . , , - , , , .
