反应(下一步)等待上下文数据并将值传递给自定义挂钩

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

我正在尝试将上下文中的数据消费到自定义挂钩中。问题是数据没有准备好,挂钩采用默认值。 上下文准备好后,如何让我的自定义挂钩采用更新的值?

定时器上下文

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


//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>
  );


};

页数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]);


问题

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
 );

改为

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 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,
};

我认为是上下文没有准备好,当hook已经在等待值的时候,但是不知道怎么解决

这里的问题是,useCounterHook 是 运行,useEffect 是基于第一次安装的,然后从不考虑 timer 值何时更改.

如果你使用 useEffect 依赖数组你可以解决这个问题。

useCounterHook 中的 useEffect 更新为以下内容,您应该可以开始了:

  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]);

现在您的钩子将检查这些输入中的任何一个是否发生变化,如果是这种情况,计时器将停止,然后使用新值启动一个新计时器。