Component is rendered again whenever some input state is changed

Asked

Viewed 197 times

0

Good morning guys. I am developing an application where the user registration is according to the option that it selects " Physical or Legal ". According to the option that he chooses a form is rendered through functions / Component, the problem is that rendering in this way whenever I change the value of some input, ie some state the page of a refresh. How could I get this problem out ?

registry js.:

import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { toast, ToastContainer } from 'react-toastify';
import './register-style.css';
import 'react-toastify/dist/ReactToastify.min.css'; 
import api from '../../services/api';

export default function Registro() {
  const [tipo, setTipo] = useState('');
  const [nomerazao, setNomeRazao] = useState('');
  const [cpfcnpj, setCpfCnpj] = useState('');
  const [password, setPassword] = useState('');
  const [email, setEmail] = useState('');
  const [sexo, setSexo] = useState('');
  const [status, setStatus] = useState('A');
  const [endereco, setEndereco] = useState('');
  const [nroendereco, setNroEndereco] = useState('');
  const [bairro, setBairro] = useState('');
  const [cidade, setCidade] = useState('');
  const [uf, setUf] = useState('');
  const [cep, setCep] = useState('');
  const [ddd, setDdd] = useState('');
  const [telefone, setTelefone] = useState('');

  function CNPJ() {
    return (
        <form onSubmit={handleRegister}>

          <input 
            placeholder="Insira sua Razão Social"
            value={nomerazao}
            onChange={e => setNomeRazao(e.target.value)}
          />

          <input 
            placeholder="Insira seu CNPJ"
            value={cpfcnpj}
            onChange={e => setCpfCnpj(e.target.value)}
          />

          <input 
            type="email" 
            placeholder="Insira seu email"
            value={email}
            onChange={e => setEmail(e.target.value)}
          />

          <button type="submit">Cadastrar</button>
        </form>
    );
  };

  function CPF() {
    return (
        <form onSubmit={handleRegister}>

          <input 
            placeholder="Insira seu Nome"
            value={nomerazao}
            onChange={e => setNomeRazao(e.target.value)}
          />

          <input 
            placeholder="Insira seu CPF"
            value={cpfcnpj}
            onChange={e => setCpfCnpj(e.target.value)}
          />

          <input
            type="password"
            placeholder="Insira sua senha"
            value={password}
            onChange={e => setPassword(e.target.value)}
          />
          

          <input 
            type="email" 
            placeholder="Insira seu email"
            value={email}
            onChange={e => setEmail(e.target.value)}
          />

          <button type="submit">Cadastrar</button>
        </form>
    );
  };

  function Form (){

    if(tipo === '') {
      return (
        <div>
          <span>Selecione um tipo de cadastro...</span>
        </div>
      )
    }else if(tipo === 'F') {
      return (
        <div>
          <CPF />
        </div>
      )
    } else {
      return (
        <div>
          <CNPJ />
        </div>
      )
    }
  }

  return (
    <div className="formulario">

    <h1>Registro</h1>

    <div className="botoes">
      <span>Tipo de cadastro: </span>
      <select value={tipo} onChange={e => setTipo(e.target.value)}>
        <option disabled value="">Selecione</option>
        <option value="F">Usuário</option>
        <option value="J">Empresa</option>
      </select>
    </div>

    <Form />

    <Link to="/">Voltar ao Login</Link>
    </div>
  );
}

Function handleRegister:

async function handleRegister(e) {
    e.preventDefault();

    const data = ({
      
    });

    try{
      await api.post('/pessoa/register', data)
          .then(function(response){
              if(response.status === 200){
                  toast.success(`${response.data.name} Seu cadastro foi realizado com sucesso !`);
                  // setTimeout(() =>{
                  //     history.push('/')
                  // }, 3250);
              }
          });
    } catch (err) {
      if(err.response.status === 400) {
          toast.error(err.response.data.error);
      }
    }
  }
  • " page of a refresh " -> the page refreshes or the component Registro render again?

  • Exactly Rafael, the component renders again. I will change until the title, I apologize for the mistake.

  • This is the expected behavior. A component renders when there is a status change. If all inputs are controlled (with useState) in the same component, the status change of the input A will cause the rendering of the entire component.

  • What happens is that your <Form /> could be a different component, since your entire page seems to be a component only. Other than that, I see no problems. If the <Form /> have child components, some other methods could be used to avoid rendering children, see this question for more details: How to use "shouldComponentUpdate" with Hooks?

  • In case you believe that if I create only one component and put it all together in one would solve my problem ?

  • I got confused because of Link in the component. If Registro represents only the form for registration, all right, no need to componentize more. It is a matter of opinion, and it is difficult to opine without having the context. I recommend reading the React documentation to try to understand what a component means and consequently when composing. PS: No problems with the code Registro, will not have performance problems as it is a very simple component today.

  • The point is, if I put any of these Forms in the "Return() " pattern of the React down there, I can type normal inputs without any component refresh or Reload. My problem is being only in the fact of rendering the form by the component, as it is always updating. And, if I take the onChange of inputs even in the component I can type normal without it rendering all the time.

Show 3 more comments

1 answer

2


Use with component and function memo that prevents such reengineering:

const Email = React.memo(({value, setValue}) => {  
  return (
    <div>   
      <div style={{height: 20}}>{value}</div>
      <input type="text" value={value} onChange={e => setValue(e.target.value)} />
    </div>
  )
});

const Password = React.memo(({value, setValue}) => {  
  return (
    <div>      
      <div style={{height: 20}}>{value}</div>
      <input type="text" value={value} onChange={e => setValue(e.target.value)} />
    </div>
  )
});



function App() {
  const [email, setEmail] = React.useState('');  
  const [password, setPassword] = React.useState('');   
  React.useEffect(() => {
    console.log('App Input Renderização');
  }, []);
  return (
    <div>
      <Email value={email} setValue={setEmail} />
      <Password  value={password} setValue={setPassword} />  
    </div>
  )
}
ReactDOM.render( <App/> , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root">Carregando ...</div>

Explanation on the website itself: If your component renders the same result given the same props, you can involve in it a call to React.memo for an increase in performance in some cases, by memoizing the result. This means that React will skip rendering the component and reuse the last rendered result.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.