-1

I am building an app with React using Remix, fly.io for deployment. I have a custom React hook useCountdown that has the following code:

import { useEffect, useState } from 'react';

const useCountdown = (targetSeconds) => {
    const countDownSeconds = targetSeconds

    const [countDown, setCountDown] = useState(countDownSeconds);

    useEffect(() => {
        const interval = setInterval(() => {
            setCountDown(countDownSeconds);

            return () => clearInterval(interval);
        }, [countDownSeconds]);

        return getReturnValues(countDown);
    }, [])
};

const getReturnValues = (countDown) => {
    const seconds = Math.floor((countDown % (1000 * 60)) / 1000);

    return [seconds];
}

export { useCountdown }


The DateTimeDisplay component has the following code and is a component dependency of the hook:

import React from 'react';

const DateTimeDisplay = ({ value, type, isDanger }) => {
    return (
        <div className={isDanger ? 'countdown danger' : 'countdown'}>
            <p>{value}</p>
            <span>{type}</span>
        </div>
    );
};

export default DateTimeDisplay;

Finally, I have a CountdownTimer component that has the following code:

import React from 'react';
import DateTimeDisplay from './DateTimeDisplay';
import ExpiredNotice from './ExpiredNotice'
import { useCountdown } from '../hooks/useCountdown';


const ShowCounter = ({ seconds }) => {
    return (
        <div className="show-counter">
                <DateTimeDisplay value={seconds} type={'seconds'} isDanger={false} />
        </div>
    );
};

const CountdownTimer = ({ targetSeconds }) => {
    const [seconds] = useCountdown(targetSeconds);

    if (seconds <= 0) {
        return <ExpiredNotice />;
    } else {
        return (
            <ShowCounter
                seconds={seconds}
            />
        );
    }
};

export default CountdownTimer;

Upon trying to utilize the useCountdown() hook, I get the following error:

TypeError: useCountdown is not a function or its return value is not iterable
    at CountdownTimer (/Users/tduke/Desktop/dev/drawesome/app/components/CountdownTimer.jsx:17:23)
    at processChild (/Users/tduke/Desktop/dev/drawesome/node_modules/react-dom/cjs/react-dom-server.node.development.js:3353:14)
    at resolve (/Users/tduke/Desktop/dev/drawesome/node_modules/react-dom/cjs/react-dom-server.node.development.js:3270:5)
    at ReactDOMServerRenderer.render (/Users/tduke/Desktop/dev/drawesome/node_modules/react-dom/cjs/react-dom-server.node.development.js:3753:22)
    at ReactDOMServerRenderer.read (/Users/tduke/Desktop/dev/drawesome/node_modules/react-dom/cjs/react-dom-server.node.development.js:3690:29)
    at renderToString (/Users/tduke/Desktop/dev/drawesome/node_modules/react-dom/cjs/react-dom-server.node.development.js:4298:27)
    at handleRequest (/Users/tduke/Desktop/dev/drawesome/app/entry.server.jsx:10:16)
    at handleDocumentRequest (/Users/tduke/Desktop/dev/drawesome/node_modules/@remix-run/server-runtime/server.js:400:18)
    at requestHandler (/Users/tduke/Desktop/dev/drawesome/node_modules/@remix-run/server-runtime/server.js:49:18)
    at /Users/tduke/Desktop/dev/drawesome/node_modules/@remix-run/express/server.js:39:22

The line in question:

    const [seconds] = useCountdown(targetSeconds);

  1. Can someone explain to me this error, and what it exactly is telling me so I understand this error in it's entirety, and what the cause is in this instance?

  2. How do I fix it?

2
  • We'll need to see useCountdown to tell you for sure. But the error is saying you can't use array destructuring (ie, the square brackets in const [seconds] =) because you didn't return an array. Commented May 28, 2022 at 17:21
  • @NicholasTower I apologize, I am new to Mac and I didn't correctly copy/paste the code. I fixed it and updated the post, if you want to have a look.
    – T. Duke
    Commented May 28, 2022 at 17:25

1 Answer 1

1

useCountdown does not have a return statement, so it's implicitly returning undefined. Then when you try to destructure undefined, you get that error because array destructuring only works on arrays (or other iterables, which is why the error mentions "iterable"s, not arrays)

You did put a return statement inside your useEffect, but returning something in a useEffect is for cleaning up the effect. It won't cause useCountdown to return anything. To fix this, move your return statement to the body of useCountdown, and move the effect cleanup to be the return from the effect:

const useCountdown = (targetSeconds) => {
    const countDownSeconds = targetSeconds

    const [countDown, setCountDown] = useState(countDownSeconds);

    useEffect(() => {
        const interval = setInterval(() => {
            setCountDown(countDownSeconds);
        }, [countDownSeconds]);

        return () => clearInterval(interval);
    }, [])

    return getReturnValues(countDown);
};

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.