1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

  2. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[ReactJS]

Discussão em 'Mobile' iniciado por Stack, Junho 17, 2021.

  1. Stack

    Stack Membro Participativo

    Estou com um problema que não consigo resolver. Estou tentando simular a perda de água no corpo de um animal ao longo do tempo, e caso o animal esteja dormindo, a quantidade de água perdida é menor.

    Dentro do primeiro UseEffect tenho um setInterval, que decrementa o estado currentValue de acordo com a prop water.decrementRate. Coloquei uma condição para que o setInterval execute somente se o animal estiver vivo. No retorno do hook eu limpo o loop com um clearInterval.

    O programa funciona até o momento em que os valores da prop water.decrementRate ou do estado IsDead são alterados. No console do navegador o erro "React Maximum update depth exceeded." ocorre iterativamente. Tentei usar as soluções que vi, colocando o array de dependencias para o useEffect, movendo a função "generateRandomNumber" para dentro do hook e utilizando Atualizações Funcionais no setState "setCurrentValue".

    Tenho o Seguinte código dentro do meu componente WaterSystem:

    import { useState, useEffect } from "react";
    import Container from "../Container/index"
    import { useIsDead } from '../../hooks/animal.hook';
    import './style.css';

    const WaterSystem = ({water}) => {

    const [currentValue, setCurrentValue] = useState(water.capacity);
    const {isDead, setIsDead} = useIsDead();

    useEffect(() => {
    function generateRandomNumber() {
    const variationRate = 0.2;
    const variationValue = water.decrementRate * variationRate;
    const max = (water.decrementRate + variationValue);
    const min = (water.decrementRate - variationValue);
    const newNumber = Math.random() * (max - min) + min;
    return newNumber;
    }

    if(!isDead){
    const id = setInterval(() => {
    setCurrentValue(oldValue => oldValue + (generateRandomNumber() * -1));
    }, 1000);

    return () => clearInterval(id);
    }
    }, [water.decrementRate, isDead]);

    useEffect(() => {
    if(currentValue <= 0)
    setIsDead(true);
    }, [currentValue, setIsDead]);

    useEffect(() => {
    if(!isDead){
    setCurrentValue(water.capacity);
    }
    }, [isDead, water.capacity]);

    return(
    <Container>
    <p>Nivel de água (Máx <b>{water.capacity}</b> ml): <b>{currentValue.toFixed(2)}</b></p>
    <p>perda de água (ml/s): <b>{water.decrementRate}</b></p>
    </Container>
    );
    }

    export default WaterSystem;


    Tenho o seguinte código no componente Animal:

    import React from "react";

    import WaterSystem from "../WaterSystem/index";
    import Botao from "../Botao/index";
    import { useWater, useIsDead, useIsSleeping } from '../../hooks/animal.hook';

    import './style.css';

    const Animal = () => {
    const {isSleeping, setIsSleeping} = useIsSleeping();
    const {isDead, setIsDead} = useIsDead();
    const water = useWater(isSleeping);

    return (
    <div>
    <h1>{isDead ? 'morto' : 'vivo'}</h1>
    <WaterSystem water={water} />
    <Botao label={isSleeping ? "awake" : "sleep"} onClick={() => setIsSleeping(!isSleeping)}/>
    {isDead && <Botao label="Reiniciar" onClick={() => setIsDead(!isDead)}/>}
    </div>
    )
    };

    export default Animal;


    Neste arquivo estou usando 3 hooks customizados provenientes do arquivo animal.hook.js:

    import { useState, useEffect, useContext } from "react";
    import { AnimalContext } from "../contexts/Animal.context";

    export function useWater(isSleep) {
    const values = {
    sleep: {
    capacity: 100,
    decrementRate: 6,
    drinkRate: 30,
    dehydrationRange: [0.05, 0.08, 0.1, 0.15]
    },
    repose: {
    capacity: 100,
    decrementRate: 10,
    drinkRate: 30,
    dehydrationRange: [0.05, 0.08, 0.1, 0.15]
    }
    };

    const [water, setWater] = useState(values.repose);

    useEffect(() => {
    if(isSleep)
    setWater(values.sleep);
    else
    setWater(values.repose);
    }, [isSleep, values.sleep, values.repose]);

    return water;
    }

    export function useIsDead() {
    const context = useContext(AnimalContext);
    const {isDead, setIsDead} = context;
    return {isDead, setIsDead};
    }

    export function useIsSleeping() {
    const context = useContext(AnimalContext);
    const {isSleeping, setIsSleeping} = context;
    return {isSleeping, setIsSleeping};
    }


    Na função useWater recebo um valor booleano isSleep para verificar se o animal esta dormindo e crio um objeto literal contendo os valores para cada condição do animal (dormindo e acordado). quando há mudança no isSleep, uso o useEffect para atribuir o corresponde valor no estado water e retorná-lo.

    As funções useIsDead e useIsSleeping retornam os estados de um contexto criado para o animal, que está presente no arquivo Animal.context.js:

    import React, { createContext, useState } from 'react';

    export const AnimalContext = createContext({});

    export const AnimalProvider = (props) => {

    const [isDead, setIsDead] = useState(false);
    const [isSleeping, setIsSleeping] = useState(false);

    return (
    <AnimalContext.Provider value={{
    isDead, setIsDead,
    isSleeping, setIsSleeping
    }}>
    {props.children}
    </AnimalContext.Provider>
    );
    }

    Continue reading...

Compartilhe esta Página