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 custom hook not rendering

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:

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

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?

>Solution :

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