3

We have made our own npm-package and I'm now working on a time out alert. To get the time out to work right I need to have it inside a useEffect but I get error: react.development.js:1465 Uncaught Error: Invalid hook call. .

The file in the component in the npm package is in typescript but I don´t think that´s the problem. .tsx:

import * as React from "react";

/**
 * @param {string} close_button_title default "Stäng"
 * @param {"top" | "bottom"} alert_position fixes the alert to bottom och top
 * @param {"warning" | "success" | "danger" | "error"} alert_type success as default
 * @param {any} alert_text plain text or html elements whit text, if empty/null/false the Alert is not shown
 * @param {any} set_alert_text the set state (hook) for alert_test (ex: setAlertText), must be right to close alert both whit timeout and the close btn
 * @param {boolean} alert_inline used to get alert message inline in modal
 */

const TimeOutAlert = (props: {
    close_button_title: string;
    alert_position?: "top" | "bottom";
    alert_type?: "warning" | "success" | "danger" | "error";
    message_wrapper_id?: string;
    alert_text: any;
    set_alert_text: any;
    alert_inline?: boolean;
}) => {
    const {
        close_button_title = "Stäng",
        alert_position = "top",
        alert_type = "success",
        message_wrapper_id = null,
        alert_text,
        set_alert_text,
        alert_inline = false,
    } = props;

    React.useEffect(() => {
        if (alert_text) {
            setTimeout(() => {
                set_alert_text("");
            }, 15 * 1000);
        }
    }, [alert_text]);

    let alertClasses = `message__alert__fixed--${alert_position}`;
    if (alert_inline) {
        alertClasses = "message__alert--inline";
    }

    if (alert_text) {
        return (
            <div
                className={`message__alert--${alert_type} ${alertClasses}`}
                id={message_wrapper_id}
            >
                {close_button_title && (
                    <button
                        className="icon icon--140 button--icon message__alert__button__close"
                        title={close_button_title}
                        onClick={() => set_alert_text("")}
                    >
                        close
                    </button>
                )}
                {alert_text}
            </div>
        );
    }
    return null;
};

export default TimeOutAlert;

index.ds

import TimeOutAlert from "./TimeOutAlert";
import OneMorefrom "./OneMore";
import Some "./Some";
import Else from "./Else";

export {
    TimeOutAlert,
    OneMore,
    Some,
    Else,
};

If I remove the useEffect, it works but then the time out don´t work as it should. When I use the package I import the component I want´t to use in my jsx-file or tsx-file. I have made ten or something components but have not used hooks in any of them except for this one.

Where I use the components App.jsx:

import React, { useState } from "react";
import { TimeOutAlert } from "our-npm-package";

export default () => {
    const [message, setMessage] = useState("Alert meddelande");

    return (
        <>
        <TimeOutAlert alert_text={message} set_alert_text={setMessage}  />

I´m using react hooks in the main projects where I import this npm package so I usually know what´s the problem is but I don´t know way it´s not working now. I don´t usually use typescript, it´s just in the npm package to get intellisense when using it but I still think that it´s react thats the problem. But I could be wrong.

EDIT:

It's the useEffect that causes the error, useState throws the same error (tried to use that for changing the alertclass).

I have used this kind of timeouts in multiple projects that's why I want it in our react-components npm-package.

The full error message in the console:

Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app
    See ... for tips about how to debug and fix this problem.

at resolveDispatcher (react.development.js:1465)
at Object.useEffect (react.development.js:1508)
at TimeOutAlert (TimeOutAlert.js:14)
at renderWithHooks (react-dom.development.js:14803)
at mountIndeterminateComponent (react-dom.development.js:17482)
at beginWork (react-dom.development.js:18596)
at HTMLUnknownElement.callCallback (react-dom.development.js:188)
at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
at invokeGuardedCallback (react-dom.development.js:292)
at beginWork$1 (react-dom.development.js:23203)

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Joe
  • 88
  • 1
  • 8
  • I think you should also provide code for the component rendering `TimeOutAlert ` – Joshua Nov 20 '20 at 10:58
  • But what I you remove setTimeout, is still the same error? – Freestyle09 Nov 20 '20 at 11:14
  • And I see you don't clear your timeout so maybe try this too: https://stackoverflow.com/questions/53090432/react-hooks-right-way-to-clear-timeouts-and-intervals – Freestyle09 Nov 20 '20 at 11:15
  • The problem is not whit the timeout, it works, it´s whit the layout-effect. I have written the same code directly in projects (not typescript). Get the same error whit useState so it´s not the timeout function that´s the problem is that react don´t except me usining useEffect – Joe Nov 20 '20 at 11:30

0 Answers0