Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

react (next) wait context data and passing values to custom hook

I am trying to consume data from context, into a custom hook. the problem is that the data is not ready and the hook takes the default values.
How can I make my custom hook take the updated values ​​once the context is ready?

timer context

the context expects two values ​​that I get from the database

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


//context
export const TimerContext = createContext();

//hook
export const useTimer = () => useContext(TimerContext);

//provider
export const TimerProvider = ({ children }) => {
  //estado del context
  const [timer, setTimer] = useState({
    inicioPartido: "Apr 8, 2022 01:00:00",
    finPartido: "Apr 8, 2022 01:10:00",
  });

  return (
    <TimerContext.Provider value={{ timer, setTimer }}>
      {children}
    </TimerContext.Provider>
  );


};

page index.js

timers it is an object that I get from the database, here everything works fine
the object exists and is stored in the context

const {timer, setTimer } = useTimer();

 useEffect(() => {
    setTimer({
      inicioPartido: timers.start_timer,
      finPartido: timers.end_timer,
    });
  }, [timers]);


the issue

when I pass both dates to my custom hook, it gets only the default values ​​that I put in the context

const { inicio, termino, segundo, minuto, hora, dia } = useCounterhook(
   timer.inicioPartido,
   timer.finPartido
 );

instead

If I send the dates hard coded everything works perfectly

const { inicio, termino, segundo, minuto, hora, dia } = useCounterhook(
   "Apr 8, 2022 03:40:00",
   "Apr 8, 2022 03:50:00"
 );

MY CUSTOM HOOK

my hook compares the distance between two dates and generates a countdown


import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";


const useCounterhook = (fechaInicio, fechaTermino) => {
  //states
  const [segundo, setSegundo] = useState(0);
  const [minuto, setMinuto] = useState(0);
  const [hora, setHora] = useState(0);
  const [dia, setDia] = useState(0);
  const [inicio, setInicio] = useState(false);
  const [termino, setTermino] = useState(false);

  //real time settings
  const second = 1000;
  const minute = second * 60;
  const hour = minute * 60;
  const day = hour * 24;

  useEffect(() => {
    setInterval(() => {
      let inicio = new Date(fechaInicio).getTime();
      let termino = new Date(fechaTermino).getTime();
      let ahora = new Date().getTime();
      let distance = inicio - ahora;

      if (inicio > ahora && termino > ahora) {
        //si fechaInicio es mayor a este instante
        //partido aun no inicia
        setDia(Math.floor(distance / day));
        setHora(Math.floor((distance % day) / hour));
        setMinuto(Math.floor((distance % hour) / minute));
        setSegundo(Math.floor((distance % minute) / second));
        setInicio(false);
        setTermino(false);
      }
      if (inicio < ahora && termino > ahora) {
        //si fecha inicio es menor a este instante
        // partido ya inicio y aun no termina
        setDia(0);
        setHora(0);
        setMinuto(0);
        setSegundo(0);
        setInicio(true);
        setTermino(false);
      }
      if (inicio < ahora && termino < ahora) {
        //si fecha inicio es mayor a fecha de termino
        //el partido ya termino
        setDia(0);
        setHora(0);
        setMinuto(0);
        setSegundo(0);
        setInicio(false);
        setTermino(true);
      }
    }, 1000);

   
  }, []);

  return { inicio, termino, segundo, minuto, hora, dia };
};

export default useCounterhook;


useCounterhook.propTypes = {
  fechaInicio: PropTypes.string,
  fechaTermino: PropTypes.string,
};

I think it is because the context is not ready, when the hook is already waiting for the values, but I don’t know how to solve it

>Solution :

The problem here is that the useCounterHook is running the useEffect based on the first time it is mounted and then never accounts for when the timer values change.

If you make use of the useEffect dependency array you can resolve this.

Update the useEffect in your useCounterHook to the following and you should be good to go:

  useEffect(() => {
    const interval = setInterval(() => {
      // this content doesn't change
    }, 1000);

    // useEffect's cleanup method
    return () => {
      clearInterval(interval)
    }
    
    // dependency array to listen if `fetchaInicio` or `fetchTermino` changes
  }, [fechaInicio, fechaTermino]);

Now your hook will check if either of those inputs change and if that is the case the timer will stop and then start a new timer with the new values.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading