3
respostas

Memo, eu entendi mau?

Estou utilizando o react com Vite.

Eu tentei colocar em prática o uso do "memo" na página inicial de minha aplicação. Ela já é simples por padrão, e simplifiquei mais ainda removendo o parâmetro do componente CLogin. Inseri o comando console.log('CLogin'); e o comando console.log('CLoginPage'); na primeira linha de cada componente. Você poderá observar abaixo que CLogin não tem componente filho, mas apenas html puro.

Observando o console os componentes continuam renderizando duas vezes. Será que entendi algo errado???? Pensei que o "memo"! evitaria esta renderização duas vezes

export default memo(CLogin); export default memo(CLoginPage);

Código de um dos componentes simplificado

import { ChangeEvent, useState, FormEvent, memo } from "react";
import { WSSecuObje } from "./WSSecuObje";
import { fHashAsync } from "../../CommonApps/Functions/Security";
import { CWSResult } from "../../CommonApps/WSClient/CWSResult";
import { CUser } from "./CUser";


function CLogin() {
  console.log('CLogin');

  const [stUserName, setstUserName] = useState<string>("");
  const [stPassword, setstPassword] = useState<string>("");
  const [stError, setstError] = useState<string | undefined>(undefined);

  async function handleSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();

    let password = await fHashAsync(stPassword);
    WSSecuObje.login(stUserName, password, (e: CWSResult<CUser>) => {
      if (!e.isSuccess) {
        setstError(e.message);
      } else {
        //onLogin(e);
      }
    });
  }

  return (
    <div className='c-d-flex-column c-w-100 c-p-32px c-bg-color-pcc'>
      <form onSubmit={handleSubmit}>

        <div className="c-d-flex-column">

          <div className="c-mb-8px">
            <label className="form-label">Usuário</label>
            <input
              className="form-control"
              onChange={(e: ChangeEvent<HTMLInputElement>) => setstUserName(e.target.value)}
              value={stUserName}
            />
          </div>

          <div className="c-mb-8px">
            <label className="form-label">Senha</label>
            <input
              className="form-control"
              onChange={(e: ChangeEvent<HTMLInputElement>) => setstPassword(e.target.value)}
              type="password"
              value={stPassword}
            />
          </div>

          <div className={"c-mb-8px" + (stError ? ' c-d-flex' : ' c-d-none')}>
            <div className="clogin__error">
                {stError}
            </div>
          </div>

          <div className="c-d-flex c-jc-center">
            <button
              className="btn btn-primary"
              type="submit">Entrar</button>
          </div>

        </div>

      </form>
    </div >
  );
}

export default memo(CLogin);

Imagem do Console

Não consegui adicionar a imagem, então vou digitar o que aparece no Console

CLoginPage (em preto) ----------- CLoginPage.tsx: 7

CLoginPage (em cinza) ------------ InstallHook.js:1

CLogin (em preto) ----------- CLogin.tsx: 17

CLogin (em cinza) ------------ InstallHook.js:1

Obrigado pela atenção sempre prestada

3 respostas

E aí! Parece que você pegou a ideia do memo no React, mas a parada pode estar um pouco confusa na hora de aplicar, né? Bora desenrolar isso!

Então, o memo no React é tipo um truque maneiro pra dar um up na performance. Ele evita ficar renderizando o componente toda hora, mas olha só: isso só rola se as props não mudarem, tá ligado?

No seu rolê, você botou o memo no CLogin. Isso quer dizer que se ele for chamado com as mesmas props, ele fica de boa e não renderiza de novo. Mas, saca só, se tiver algo dentro do CLogin que mude de estado, ele vai renderizar de novo, mesmo com o memo.

Dando uma olhada no que você mostrou no console, vi que o CLogin tá sendo chamado duas vezes. Pode ser por uns motivos:

Se tiver algo mexendo lá dentro que faça ele renderizar de novo.

Tipo, se stUserName, stPassword ou stError mudarem, o CLogin vai renderizar de novo, mesmo com o memo.

Se as props do CLogin mudarem muito, ele vai renderizar de novo, a menos que você também use memo nelas.

Então, pra ir mais a fundo nisso:

  • Vê se tem algo esquisito dentro do CLogin que possa estar causando esse trampo.
  • Confirma se as props pro CLogin não estão mudando toda hora e se tão sendo manejadas direito.
  • Se quiser evitar essas renderizações sem noção, dá uma revisada no que tá rolando dentro do CLogin.

Espero que isso jogue umas luzes no rolê! Se tiver mais dúvidas ou precisar de algo, cola comigo que a gente troca uma ideia.

Bom eu já tinha avaliado estas questões.

  1. Quanto a props, eu removi a única propriedade que ele tinha. Então ele não tem nenhuma propriedade.

  2. Quanto aos estados, stUserName, stPassword ou stError. Elas só mudam se ocorrer alguma digitação ou clique no botão. Mas o componente renderiza duas vezes logo que é carregado. Nem dá tempo para uma interação de teclado ou mouse.

Muito estranho...

Descobri algo.

  1. Quando estou rodando em modo de depuração "npm run dev", é renderizado duas vezes mesmo usando o memo.

  2. Quando compilo "npm run build" e rodo pelo IIS, ele não renderiza duas vezes.

Isto deve ser uma característica do Vite.