Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 6283

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 60k
Author
Asked: November 27, 20242024-11-27T05:05:08+00:00 2024-11-27T05:05:08+00:00

React TypeScript Hooks issue when returning array

  • 60k

Read in light, dark or sepia mode on my blog

React and TypeScript make for a mean pair. Combined, they can rule the whole world together. But sometimes, these two can get off on a tangent about some small details, and we the devs have to be the scapegoat in their battle of egos. One such problem is when we're making our own custom hooks, which return an array of a value and a function, just like useState.

const [state, setState] = useState(null); 
Enter fullscreen mode Exit fullscreen mode

It's clearly visible that state is a value, and setState is a function. When you use this hook, everything works out fine, and these 2 have their own types on them.

But the issue happens when you're trying to make your own hook that returns an array, very similar in structure to useState. Let's see an example:

import { useState } from 'react';  export function useTheme() {   const [theme, setTheme] = useState('light');    // Do epic stuff here    // Return the 2 state variables   return [theme, setTheme]; } 
Enter fullscreen mode Exit fullscreen mode

Here we have a useTheme hook, which manages our theme switching magic. Here, we declare state variables, theme, with its setter useTheme. Then we do some Web dev kung fu in using these 2 variables. Lastly we're returning an array of [theme, setTheme], so we can utilise the theme and change it from anywhere. All fine.

Until you try to use this hook 😈

Let's say you're writing a component whose job is to switch the theme, and it uses our useTheme hook to do it.

You create a function to change the theme using setTheme exported from this hook:

const [theme, setTheme] = useTheme();  const toggleTheme = () => setTheme(theme === 'light' ? 'dark' : 'light'); 
Enter fullscreen mode Exit fullscreen mode

And you run into a weird error:

Array type weird error

The error according to TypeScript is:

This expression is not callable. Not all constituents of type 'string | Dispatch<SetStateAction<string>>' are callable. Type 'string' has no call signatures.ts(2349) 
Enter fullscreen mode Exit fullscreen mode

That's weird. Why is that happening?

(TLDR) Solution

Before I jump into the explanation, here's the final solution directly.

Option 1

Make this function's return type a Tuple(See the section below for the explanation).

import { useState, useEffect } from 'react';  type TTheme = 'light' | 'dark';  export function useTheme(): [string, React.Dispatch<React.SetStateAction<string>>] { ... 
Enter fullscreen mode Exit fullscreen mode

This will return a Tuple instead of an Array, so every element will have its own separate type. The error will be resolved

Option 2

This is the less verbose way, and I prefer this one over the 1st one.

import { useState, useEffect } from 'react';  type TTheme = 'light' | 'dark';  export function useTheme() {   ...    return [theme, setTheme] as const; } 
Enter fullscreen mode Exit fullscreen mode

as const here might look weird, but it's perfectly valid. In this case, it makes TypeScript infer the array being returned as a readonly tuple. This will work perfectly.

Explanation

If you see closely, the type of setTheme here is showed as

string | React.Dispatch<React.SetStateAction<string>> 
Enter fullscreen mode Exit fullscreen mode

But that's weird. We clearly know that setTheme is a function. If you hover over it in your editor, you can confirm it's type is React.Dispatch<React.SetStateAction<string>>, it doesn't have any string type as a constituent.

But wait, that's not it. If you hover over theme, it's type is the same as setState above.

And when you hover over useTheme, you find that it returns an Array of the type above 👇

(string | React.Dispatch<React.SetStateAction<string>>)[] 
Enter fullscreen mode Exit fullscreen mode

What the hell is going on

This is weird. How can we have TypeScript separate the types for each item?

Answer here is tuples.

Tuples in TypeScript

Tuples look exactly like Arrays. Here's an Array:

[2, 'hello', true]; 
Enter fullscreen mode Exit fullscreen mode

And here's a tuple:

[2, 'hello', true]; 
Enter fullscreen mode Exit fullscreen mode

The difference between the two? 1st one's type, as inferred by TypeScript, is (number | string | boolean)[], while second one's type inference is [number, string, boolean]. In the Array example, TypeScript is assigning the same type to every single item, because technically, that's the definition of an Array.

An array is a data structure that contains a group of elements. Typically these elements are all of the same data type, such as an integer or string.

All are of same types. That's why TypeScript assigns same type to every single element, by combining all possible types from the array elements using union type operator(|).

Tuples, on the other hand, are ordered pair. That means, in the order you define the types, that's the order you enter them into a tuple. So TypeScript infers them correctly, based on the array index.

Defining a tuple type

This is simple. Just specify the types in the order they appear.

const coordinates: [number, number] = [23.4, 43.67]; 
Enter fullscreen mode Exit fullscreen mode

Simple, right 🙂

Conclusion

So this is the end of this article. Hope you got something good away from it.

Signing off.

hooksreacttypescriptwebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 1k
  • Popular
  • Answers
  • Author

    How to ensure that all the routes on my Symfony ...

    • 0 Answers
  • Author

    Insights into Forms in Flask

    • 0 Answers
  • Author

    Kick Start Your Next Project With Holo Theme

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.