2

enter image description here

As can be seen in the image, I want to declare a react state hook to the alert of my webpage. At first, I want that there is no alert shown. And whenever user is clicking some button, I want to show a success alert with a message (error alert if something goes wrong). I will call showAlert function to do this with message and type as function parameter. That's why there can be more than one type of alert. So, I created this alert object and attached hook with initial value "NULL". But the editor gives me this error.

Argument of type '{ msg: any; type: any; }' is not assignable to parameter of type 'SetStateAction<null>'. Object literal may only specify known properties, and 'msg' does not exist in type '(prevState: null) => null'.ts(2345)

So, can someone tell me how I can tell useState the object parameters that I will allot it in future. Or should I try to hide the website alert in some other way? Here is the code..

const [alert, setAlert] = useState(null);

const showAlert = (message, type) => {
    setAlert({
        msg: message,
        type: type,
    });

    setTimeout(() => {
        setAlert(null);
    }, 2000);

enter image description here

This solution is not working for me.

Bittu Joshi
  • 110
  • 2
  • 10
  • 1
    Please replace the image of code with a text-based [mcve] – evolutionxbox Jul 05 '22 at 13:54
  • 1
    Define the type of the state `useState(null as any)` – Rashomon Jul 05 '22 at 13:55
  • 1
    `useState<{msg: string, type: string}>(null)`. In case if you have strict null checks on in your tsconfig, you will not able to set null. Either you can remove that from tsconfig or you can `useState<{msg: string, type: string} | null>(null)` – Dilshan Jul 05 '22 at 13:56
  • @Rashomon I have tried that. I get these two erros. 1. Parsing error: Unexpected token, expected "," (10:41)eslint {squigly error on null word} 2. Type assertion expressions can only be used in TypeScript files.ts(8016) {error line under any word} – Bittu Joshi Jul 05 '22 at 13:59
  • @Dilshan I am getting these errors for your solution. 1. Type 'number' must have a '[Symbol.iterator]()' method that returns an iterator.ts(2488) 2. (property) msg: any Operator '<' cannot be applied to types '{ (initialState: S | (() => S)): [S, Dispatch>]; (): [S | undefined, Dispatch>]; }' and '{ msg: any; type: any; }'.ts(2365) The '|' operator is not allowed for boolean types. Consider using '||' instead.ts(2447) 3. Comparing to itself is potentially pointless.eslintno-self-compare Object is possibly 'null'.ts(2531) – Bittu Joshi Jul 05 '22 at 14:01

4 Answers4

3

From the looks of the error you mentioned, it seems you're using TypeScript.

One way to achieve the desired outcome is to use generics.

const [alert, setAlert] = useState<{
  msg: string;
  type: "success" | "error";
} | null>(null);

Furthermore, you can improve readability by adding an enum and a type.

enum AlertType {
  Success,
  Error,
}

type Alert = {
  msg: string;
  type: AlertType;
}

const [alert, setAlert] = useState<Alert | null>(null);
  • 1
    I am using javascript only but it seems like I am getting typesript errors in javascript. Also the solution you gave will not work because type aliases and enum declarations aren't supported in javascript. – Bittu Joshi Jul 05 '22 at 18:10
  • 1
    I've assumed that you're using TypeScript, hence the nature of the solution. You are correct, this will not work in a JavaScript context. @BittuJoshi , it seems that VSCode has implicit TS validation even for JS files. You can give [this one a try](https://medium.com/lessons-from-debugging/remove-ts-errors-from-js-files-3970d1a5336c). – Răzvan Sbîngu Jul 10 '22 at 11:24
2

You need to declare your useState a little differently

const [alert, setAlert] = useState<{ msg: any; type: any } | null>(null);

Another alternative is the use undefined

const [alert, setAlert] = useState<{ msg: any; type: any } | undefined>();

Hope that helps.

Joseph King
  • 5,089
  • 1
  • 30
  • 37
  • Operator '<' cannot be applied to types '{ (initialState: S | (() => S)): [S, Dispatch>]; (): [S | undefined, Dispatch>]; }' and '{ msg: any; type: any; }'.ts(2365) ----The '|' operator is not allowed for boolean types. Consider using '||' instead.ts(2447) ----'any' only refers to a type, but is being used as a value here.ts(2693)-----Object is possibly 'null'.ts(2531) – Bittu Joshi Jul 05 '22 at 18:05
2

You can do it below way for useState type

type AlertType = {
 msg: string;
 type: string; // you can specify enum also
}

const [alert, setAlert] = useState<AlertType|null>(null);

const showAlert = (message, type) => {
    setAlert({
        msg: message,
        type: type,
    });

    setTimeout(() => {
        setAlert(null);
    }, 2000);
Bhavesh Daswani
  • 707
  • 6
  • 11
  • 'AlertType' is declared but never used.ts(6196) Type aliases can only be used in TypeScript files.ts(8008) I am using javascript – Bittu Joshi Jul 05 '22 at 18:07
1

There are 2 solutions:

1: useState(null as any)
2: useState({ msg: any, type: any })
Asad Ashraf
  • 1,425
  • 8
  • 19
  • 1. Parsing error: Unexpected token, expected "," (10:41)eslint {error line under null} and Type assertion expressions can only be used in TypeScript files.ts(8016) {error line under any} 2. 'any' only refers to a type, but is being used as a value here.ts(2693) 'any' is not defined.eslintno-undef – Bittu Joshi Jul 05 '22 at 17:58