Jaburu
Jaburu

Reputation: 3

Error: Too many re-renders. React limits the number of renders

I am trying to filter an array, but when a try to get the results with useState this error occurs. I've already tried to put it in a Callback function and it didn't work...

Important code fragment:

const pedidosFiltro = pedidos
    .filter((p) => p.cliente === chosenCliente)
    .map((a) => a.origem);

  setOrigensFilter(pedidosFiltro);

Full Code:

import React, { useState, useEffect } from "react";
import "./App.css";
import axios from "axios";

// !!! FAZER OS FILTROS PARA TODOS OS ELEMENTOS DO PEDIDO !!!

function App() {
  // Constante com um array e todos os pedidos:
  const [pedidos, setPedidos] = useState([]);

  // Constantes escolhidas pelo usuário
  const [chosenOrigem, setChosenOrigem] = useState("");
  const [chosenUnidade, setChosenUnidade] = useState("");
  const [chosenCliente, setChosenCliente] = useState("");

  // Constantes criadas para fazer consultas coluna por coluna
  const [origens, setOrigens] = useState([]);
  const [unidades, setUnidades] = useState([]);
  const [clientes, setClientes] = useState([]);

  // Constantes para armazenar conteúdos vindos do pedidosFilter
  const [origensFilter, setOrigensFilter] = useState([]);

  var finalOrigens = origens.map((obj) => {
    return obj.origem;
  });

  var finalUnidades = unidades.map((obj) => {
    return obj.unidade;
  });

  var finalClientes = clientes.map((obj) => {
    return obj.cliente;
  });

  // Getting rid of duplicate elements in a array:
  var uniqueOrigens = [...new Set(finalOrigens)];
  var uniqueUnidades = [...new Set(finalUnidades)];
  var uniqueClientes = [...new Set(finalClientes)];

  const pedidosFiltro = pedidos
    .filter((p) => p.cliente === chosenCliente)
    .map((a) => a.origem);

  setOrigensFilter(pedidosFiltro);

  useEffect(() => {
    // Pegando coluna por coluna dos pedidos:
    const getOrigens = () => {
      axios.get("http://localhost:5000/api/get/origens").then((response) => {
        setOrigens(response.data);
      });
    };

    const getUnidade = () => {
      axios.get("http://localhost:5000/api/get/unidades").then((response) => {
        setUnidades(response.data);
      });
    };

    const getCliente = () => {
      axios.get("http://localhost:5000/api/get/clientes").then((response) => {
        setClientes(response.data);
      });
    };

    // Pegando todos os pedidos aclopados:
    const getPedidos = () => {
      axios.get("http://localhost:5000/api/get/pedidos").then((response) => {
        setPedidos(response.data);
      });
    };

    // Chamando função de todos os pedidos:
    getPedidos();

    // Chamando funções para pegar coluna por coluna nos pedidos:
    getOrigens();
    getUnidade();
    getCliente();
  }, []);

  return (
    <div className="App">
      <select
        value={chosenOrigem}
        onChange={(e) => {
          setChosenOrigem(e.target.value);
          console.log(chosenOrigem);
        }}
      >
        {uniqueOrigens.map((origem, index) => {
          return <option key={index}>{origem}</option>;
        })}
      </select>

      <select
        value={chosenUnidade}
        onChange={(e) => {
          setChosenUnidade(e.target.value);
          console.log(chosenUnidade);
        }}
      >
        {uniqueUnidades.map((unidade, index) => {
          return <option key={index}>{unidade}</option>;
        })}
      </select>

      <select
        value={chosenCliente}
        onChange={(e) => {
          setChosenCliente(e.target.value);
          console.log(chosenCliente);
        }}
      >
        {uniqueClientes.map((cliente, index) => {
          return <option key={index}>{cliente}</option>;
        })}
      </select>

      <h4 className="resultados">Resultados:</h4>
      {pedidos
        .filter(
          (pedido) =>
            pedido.origem === chosenOrigem &&
            pedido.unidade === chosenUnidade &&
            pedido.cliente === chosenCliente
        )
        .map((filteredPedido) => (
          <div className="dataBox">
            <h4>Origem: {filteredPedido.origem}</h4>
            <h4>Pedido: {filteredPedido.pedido}</h4>
            <h4>Unidade Carga: {filteredPedido.unidade_carga}</h4>
            <h4>Unidade: {filteredPedido.unidade}</h4>
            <h4>Cliente: {filteredPedido.cliente}</h4>
            <h4>Quantidade Pedida: {filteredPedido.quantidade_pedido}</h4>
            <h4>Data de Entrega: {filteredPedido.data_entrega}</h4>
            <h4>Data de Embarque: {filteredPedido.data_embarque}</h4>
            <h4>Incoterm: {filteredPedido.incoterm}</h4>
            <h4>Peso: {filteredPedido.peso}</h4>
            <h4>Tipo Unidade Carga: {filteredPedido.tipo_unidade_carga}</h4>
            <h4>Largura UC: {filteredPedido.largura_uc}</h4>
            <h4>Comprimento UC: {filteredPedido.comprimento_uc}</h4>
            <h4>Altura UC: {filteredPedido.altura_uc}</h4>
            <h4>Produto: {filteredPedido.produto}</h4>
          </div>
        ))}
    </div>
  );
}

export default App;

Upvotes: 0

Views: 81

Answers (1)

akram-adel
akram-adel

Reputation: 1070

You shouldn't leave setOrigensFilter in the app function like this, try wrapping it inside its own function like so:

function setOrigensFilterHandler () {
  const pedidosFiltro = pedidos
    .filter((p) => p.cliente === chosenCliente)
    .map((a) => a.origem);

  setOrigensFilter(pedidosFiltro);
}

and execute it when needed.

Explanation setOrigensFilter sets the app state which causes a to rerender of the App() function, but rerendering the App() function will call setOrigensFilter, which in turn will trigger another rerender. and on and on in this loop, so in the end React gives you this Too many rerenders error.

Upvotes: 1

Related Questions