React with Hooks, useState, the value sends to each input and does not show on the screen.?

Asked

Viewed 332 times

1

I’m doing a compound interest calculation.

I receive the form data valores.js, called by function enviarValores() with the onSubmit={handleSubmit(enviarValores)} and I want to send the answers results (an array) for the Resultados.js

however, for each input, in console.log, it already shows the results. But it does not show on the screen. Only when I input new data.

inserir a descrição da imagem aqui

Doubt, how to make it call Results.js only when I click the submit button?

And what’s wrong with showing the data on the screen?

Archives

Values.js

import useForm from "../../controllers/useForm";
import { Container } from "./styles";
import Resultados from "../resultados/Resultados";


export default () => {
    const [{ values, loading }, handleChange, handleSubmit] = useForm();
    const [results, setResults] = useState([]);

    const enviarValores = () => {
      const capitalInicial  = parseFloat(values.montanteInicial) || null;
      const rate    = parseFloat(values.taxaJurosMensal) || null;
      const period  = parseInt(values.periodoMeses) || null;

      let totalAmount = 0;
      // let valorMensalPorcentagem = 0;
      let valorMensal = 0;
      let taxaJurosPorcentagem = rate / 100;

      for (let i = 1 ; i <= period ; i++) {

        totalAmount = capitalInicial * ((1 + taxaJurosPorcentagem)**i);

        valorMensal = totalAmount - capitalInicial;

        results.push({ month: i, totalAmount: totalAmount.toFixed(2), valorMensal: valorMensal.toFixed(2)});
      };
    };

    useEffect(() => {
      return () => {
        setResults(results);
      }
    },);

    return (
      <div className="row">
        <Container>
          <div className="row titulo">
            <h1>Juros Composto</h1>
          </div>
          <form className="col s12" onSubmit={handleSubmit(enviarValores)}>
            <div className="row">
              <div className="input-field col s6">
                <input
                  onChange={handleChange}
                  name="montanteInicial" 
                  id="montanteInicial" 
                  type="number" 
                  className="validate"
                  required 
                  step="0.01"
                  min="1000" 
                  max="99999"
                />
                <label htmlFor="montanteInicial">Montante Inicial</label>
              </div>
            </div>
            <div className="row">
              <div className="input-field col s6">
                <input
                  onChange={handleChange}
                  name= "taxaJurosMensal" 
                  id="taxaJurosMensal" 
                  type="number" 
                  className="validate"
                  required 
                  step="0.01"
                  min="-99999.99" 
                  max="999999.99" 
                />
                <label htmlFor="taxaJurosMensal">Taxa de Juros Mensal</label>
              </div>
            </div>
            <div className="row">
              <div className="input-field col s6">
                <input
                  onChange={handleChange}
                  type="number" 
                  id="periodoMeses" 
                  name="periodoMeses" 
                  className="validate" 
                  required 
                  pattern="[0-9]+$"
                  min="1" 
                  max="90"
                />
                <label 
                  htmlFor="periodoMeses" 
                  data-error="Preencha o campo com a quantidade de meses" 
                  className="active">Período (meses)
                </label>
              </div>
            </div>
            <button className="btn waves-effect waves-light" type="submit" name="action">{loading ? "Enviando..." : "Enviar"}</button>
          </form>
        </Container>

        <Resultados results={results} />

      </div> 
    
    );
}

Results.js


function Resultados({results}) {
    
    console.log(results);
    
    
    return(
        <div>
            <ul>
                { results.map((row, i) => 
                    <li key={i}>
                    <strong scope='row'>{row.month}</strong>
                    <p>R${row.totalAmount}</p>
                    </li>
                )}
            </ul>
        </div>
    )
}

export default Resultados;

The code is available at https://stackblitz.com/edit/juros-compostos

code after the change

  const enviarValores = () => {
      const capitalInicial  = parseFloat(values.montanteInicial) || null;
      const rate    = parseFloat(values.taxaJurosMensal) || null;
      const period  = parseInt(values.periodoMeses) || null;
      const resultsAux = [];

      let totalAmount = 0;
      // let valorMensalPorcentagem = 0;
      let valorMensal = 0;
      let taxaJurosPorcentagem = rate / 100;

      for (let i = 1 ; i <= period ; i++) {

        totalAmount = capitalInicial * ((1 + taxaJurosPorcentagem)**i);

        valorMensal = totalAmount - capitalInicial;

        resultsAux.push({ month: i, totalAmount: totalAmount.toFixed(2), valorMensal: valorMensal.toFixed(2)});
      };
      setResults(resultsAux);
    };

    useEffect(() => {
      return () => {
        setResults([]);
      }
    },[]);


function Resultados({results}) {
    
    
    return(
        <Container>
            <ul>
                { results.map((row, i) => 
                    <li key={i}>
                    <strong scope='row'>{row.month}</strong>
                    <p>R${row.totalAmount}</p>
                    </li>
                )}
            </ul>
        </Container>
    )
}

1 answer

1


Hello, Rebecca!

From what I understand in your code, you tried to enter values to estado result using the result.push. The correct to enter values in this case would be to use:

setResult([
   ...results, 
   { month: i, 
     totalAmount: totalAmount.toFixed(2), 
     valorMensal: valorMensal.toFixed(2)
   }
])

Correct when assigning data to a state is SEMPRE use its function, and not assign directly.

  • I did it this way, but he just entered the last record of the loop. How to use inside the for??? for (let i = 1 ; i <= period ; i++) {&#xA;&#xA; totalAmount = capitalInicial * ((1 + taxaJurosPorcentagem)**i);&#xA;&#xA; valorMensal = totalAmount - capitalInicial;&#xA;&#xA; setResults([&#xA; ...results, &#xA; { month: i, &#xA; totalAmount: totalAmount.toFixed(2), &#xA; valorMensal: valorMensal.toFixed(2)&#xA; }&#xA; ])

  • I got it, I’ll put the code with the result.

  • 1

    Great that you got!! You have to be very careful when using Set of some state within the for, because the set function of States does not return value at runtime, they are asynchronous

Browser other questions tagged

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