0

I have a custom useEffect hook to get current time every minute.

const useDateStatus = () => {
  const [date, setDate] = useState(new Date());

  useEffect(() => {
    const interval = setInterval(() => {
      setDate(() => new Date());
    }, 60000); 
    return () => clearInterval(interval);
  }, []);

  return date;
};

I need to a common component that when the date fall in the given time range, the component renders null, otherwise it will display the date.

const DateAlert = ({timeRanges, children}) => {
  const date = useDateStatus();

  if (!inRanges(date, timeRanges)) {
    return null;
  }

  return (
    <Alert>
      <p>{date}</p>
      {children}
    </Alert>
  );
};

I also need another common component that don't need the date object.

const Display = ({timeRanges, children}) => {
  const date = useDateStatus();

  if (!inRanges(date, timeRanges)) {
    return null;
  }

  return children;
};

Should I create a context to contain the date in order to pass the date props and then make the DateAlertto use the context?

const context = React.createContext(new Date());
const DateContext = ({children}) => {
  const date = useDateStatus(new Date);
  return (
    <context.Provider value={date}>
      {children}
    </context.Provider>
  );
}

I need to get the date state, from How to pass props to {this.props.children}, I think it's good to use context to pass the date as props to children.

What's the difference between using the context to get the date or directly call useDateStatus() to get the date?

Or is there a better way to reduce the redundancy between DateAlert and Display?

eriee
  • 416
  • 2
  • 15

1 Answers1

1

I'd recommend making one component and then using that component for both like such:

const RenderIfInRange = ({timeRanges, children}) => {
  const date = useDateStatus();

  if (!inRanges(date, timeRanges)) {
    return null;
  }

  return children;
};

That becomes your Display component. Then:

const DateAlert = ({children}) => (
    <RenderIfInRange>
      <Alert>
        <p>{date}</p>
        {children}
      </Alert>
    </RenderIfInRange>
  );

I'd recommend looking into Truefit's Bach. It allows you to use the HOC pattern for hooks and makes the code look a lot neater in my opinion.

  • Hi @Wilhelm, i suppose using this approach, `DateAlert` cannot get the `date` state from `RenderIfInRange`. – eriee Nov 06 '19 at 21:50
  • You can expose the date as a prop if you want to. See https://stackoverflow.com/questions/32370994/how-to-pass-props-to-this-props-children for instructions/inspiration – Wilhelm Erasmus Nov 06 '19 at 22:16
  • I have looked into it before. I think the cloneElement seems weird and some comments said it doesn't work. That's why i'm looking into the context from this answer https://stackoverflow.com/a/39401252/4157010 – eriee Nov 06 '19 at 23:05
  • Well, you could still pass it via context I guess. It depends on your use case. – Wilhelm Erasmus Nov 07 '19 at 06:41