Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

Estou passando uma função d componente A(pai) para um componente B(filho), porem dentro desta função estou usando useStates em 2 variáveis que são definidas na classe A(pai). E quando esta função é chamada na classe filho o seguinte erro acontece.

Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

Segue o código abaixo:

Classe Pai

export default function Heatmap() {
    const [remainingHeight, setRemainigHeight] = useState<number>(StockPanelSize.HEIGHT);
    const [remainingWidth, setRemainingWidth] = useState<number>(StockPanelSize.WIDTH);
    const stocks: IStock[] = [
        {
            id: 1,
            name: 'example 1',
            value: 1.50,
            volume: 150
        }        
    ];
    const panelSize = {
        height: StockPanelSize.HEIGHT + 'px',
        width: StockPanelSize.WIDTH + 'px'
    };

    function getTotalVolume(): number {
        return stocks.reduce((sum, element) => sum + element.volume, 0);
    }

    function getSize(volume: number): number[] {
        const squareSize = Math.sqrt((volume * StockPanelSize.TOTALAREA) / getTotalVolume());
        let x: number;

        //recalculates the square height
        if (StockPanelSize.HEIGHT < squareSize) {
            x = ((Math.pow(squareSize, 2) - (StockPanelSize.HEIGHT * squareSize)) / StockPanelSize.HEIGHT);
            console.log(x);

            setRemainingWidth(remainingWidth - (squareSize + x));
            return [StockPanelSize.HEIGHT, squareSize + x];
        }
        if (StockPanelSize.WIDTH < squareSize) {
            x = ((Math.pow(squareSize, 2) - (StockPanelSize.WIDTH * squareSize)) / StockPanelSize.WIDTH);
            console.log(x);

            setRemainigHeight(remainingHeight - (squareSize + x));
            return [squareSize + x, StockPanelSize.WIDTH];
        }
        return [squareSize, squareSize];
    }

    return (
        <main className={styles.heatmap} style={panelSize}>
            {stocks.map(stock => (
                <Stock
                    key={stock.id}
                    {...stock}
                    getSize={getSize(stock.volume)}
                />
            ))}
        </main>
    );
}

Classe filho:

export default function Stock(props: Props) {
    const { id, name, value, volume, getSize } = props;
    const [height, setHeight] = useState<number>(0);
    const [width, setWidth] = useState<number>(0);

    useEffect(() => {
        const [h, w] = getSize;
        setHeight(h);
        setWidth(w);
    }, []);

    return (...);
}
1 resposta
solução!

Fala Guilherme, tudo certo?

Provavelmente isto está acontecendo por causa dessa linha aqui:

<Stock
        key={stock.id}
       {...stock}
       getSize={getSize(stock.volume)} // < essa
/>

Neste caso aqui, sempre que o Stock é renderizado, ele executa o getSize instantaneamente, o getSize executa um setState, o setState muda o Stock, o Stock executa o getSize e isto vira um loop infinito.

Caso você queira que o Stock execute o getSize apenas quando ele quiser (utilizando props.getSize()) troque por isto daqui:

<Stock
        key={stock.id}
       {...stock}
       getSize={() => getSize(stock.volume)} // < essa
/>

Neste caso você não está enviando como prop o retorno da função executada, e sim uma função anônima que o componente Stock consegue executar quando ele quiser, entendeu?

Bons estudos!