DEV Community

Cover image for React + Typescript === "headache"

React + Typescript === "headache"

Vinicius Cerqueira Bonifácio on December 09, 2020

Hi, dear devs. Long time I haven't written anything here. I hope everybody is doing well. Before you think I am here making criticism about the ...
Collapse
 
stereobooster profile image
stereobooster

I like the title and the cover image.

TypeScript can do type inference, so you don't need to provide types everywhere.

This will work the same:

let myName = "Vinicius"
let myAge = 99
const [pokemon, setPokemon] = useState<Pokemon | null>(null);
Enter fullscreen mode Exit fullscreen mode

Also I would not use separate file for interface, just place it in the top of the component (it will make your life a bit easier)

Collapse
 
vinicius77 profile image
Vinicius Cerqueira Bonifácio

Thanks a lot for your comment and insights. :)

I will definitively adopt your approach and also refactor the code following your suggestions.

Collapse
 
stereobooster profile image
stereobooster • Edited
import React, { useState, useEffect } from "react";
import axios from "axios";

type Pokemon = {
  name: string,
  base_experience: number,
  numberOfAbilities: number,
  imageURL: string
}

type UseGet<Data> = {
    data: Data | undefined,
    loading: boolean,
    error: string  | undefined
}

const useGetPokemon = (name: string) => {
  const [state, setState] = useState<UseGet<Pokemon>>({
    loading: false,
    error: undefined
    data: undefined,
  });

  useEffect(() => {
    const source = axios.CancelToken.source();
    const cancelToken = source.token;
    setState({
      loading: true,
      error: undefined,
      data: undefined,
    });
    axios.get(`https://pokeapi.co/api/v2/pokemon/${name}`, {
        cancelToken,
        headers: { "Content-Type": "application/json" },
      }).then(({ data }) => {
        setState({
          loading: false,
          error: undefined,
          data: {
            name: data.name,
            base_experience: data.base_experience,
            imageURL: data.sprites.front_default,
            numberOfAbilities: data.abilities.length,
          },
        });
      }).catch((error) => {
        if (!axios.isCancel(error)) {
          setState({
            loading: false,
            error: error.message,
            data: undefined,
          });
        }
    });
    return () => source.cancel();
  }, [name, setState]);

  return state;
}

const PokemonSearch: React.FC = () => {
  const [inputName, setInputName] = React.useState("bulbasaur");
  const { data: pokemon, error, loading } = useGetPokemon(inputName);
  // ...
}
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
vinicius77 profile image
Vinicius Cerqueira Bonifácio • Edited

What could I say? You definitively nailed it! 👏

I have to admit that reading your code brought me some kind of satisfaction.

Let's agree (or not) that being my first time trying TS I was not that bad, I guess. 😅
Also in my defense I didn't invest too much time in other parts of the code but sir, let's be honest here, your version rocks!

By the way, may I ask you one question?
I have noticed the way you created the cancellation token and I would like to know it the approach below is also right because I have been using it since always. I mean, regarding good practices.

useEffect(() => {
    let cancel; 
    axios
        .get(`https://pokeapi.co/api/v2/pokemon/${name}`, {
        cancelToken: new axios.CancelToken((ctoken) => (cancel = ctoken)),
      })
    //...
    return () => cancel();
}
Enter fullscreen mode Exit fullscreen mode

Thanks again for participating, I really appreciate it! 🙏

Thread Thread
 
stereobooster profile image
stereobooster • Edited

I never meant it as a challenge. I know that using TS is hard and wanted to show alternative approach.

Regarding cancel question: theoretically provided code can go wrong because of asynchronous functions, but probably in practice you will never see problems. In your code TS will complain about cancel being used before assignment (probably)

Thread Thread
 
vinicius77 profile image
Vinicius Cerqueira Bonifácio

Please, don't get me wrong. It was not a challenge at all.

I really just wanted to report my first experience with TS but I think it is important to highlight the alternative you provided, for people like me who are giving the first steps with the language. For example, I'll surely use it as a reference and probably other people too.

Thanks for the explanation about the cancelling token. Until now I have had no problems but considering changing the way I use it. :)

I have learned a lot from the example you provided! Thanks for that.

Collapse
 
ecyrbe profile image
ecyrbe

You should not add typings to things you get back from a function, (like useState), there is what is called type inference and you should use it extensively.
You usually only need to add typing to your input parameters if you use type inference correctly.

even in c++ now everybody uses type inference everywhere.

Collapse
 
vinicius77 profile image
Vinicius Cerqueira Bonifácio

Thanks for the hint!

I am going to be aware of type inference from now on. :)

Collapse
 
peacefullatom profile image
Yuriy Markov

Great article, thank you!
By the way, I'm using typescript everywhere and it makes my life easier. Especially if you return to the codebase which you haven't touched for a long time :)

Collapse
 
andrewbaisden profile image
Andrew Baisden

Agreed TypeScript is much better once you get the hang of it.

Collapse
 
peacefullatom profile image
Yuriy Markov

Just keep on learning. With time it will become your friend :)

Collapse
 
vinicius77 profile image
Vinicius Cerqueira Bonifácio

Hi, Yuriy.

Thanks a lot for your comment. I really appreciate it. :)

I tried to describe my first-time experience using TS instead JS. I exaggerated typing more than I should as other developer spotted it but I really enjoyed the ride!

Did you face the same issues when started using TS? Feel free to share your experience with us. :)

I am sure it is very handy when dealing again with the codebase after a while. Trying to figure out what code does is always very time consuming. At least for me it is. XD

Collapse
 
peacefullatom profile image
Yuriy Markov

Well, for me this story went a bit different. :)
My first programming language was C++. So, when I switched to JS it was a pretty nightmare for me - the lack of types. :D
And when the TS emerged I was very happy. From my point of view, it gets better with each release.
Happy coding!

Thread Thread
 
vinicius77 profile image
Vinicius Cerqueira Bonifácio

Really interesting story, Yuri. Thanks for sharing it!

I have never tried C++ but I read about it and it seems a very powerful tool.

I kind of understand the nightmare you had. Java was my first language ever but I ended up having my first job experience as a Ruby on Rails developer. 😂 It was kind of funny.

In my humble opinion, Java and Typescript look like similar somehow. Please don't judge if you don't. :D

I am just giving the first steps with TS but after a while getting lost and messing up a lot I started to like it. Hehe

Happy Hacking!

Collapse
 
akashkava profile image
Akash Kava

Typing has limits in functional programming, TypeScript offers good solution for 90% of the time, but it’s impossible to provide 100% typing and that requires lot of efforts as well. But as with other typed languages, TypeScript comes very handy with OOPS, and having best of both makes it easier.

Collapse
 
vinicius77 profile image
Vinicius Cerqueira Bonifácio

Thanks for commenting, Akash. :)

I still have lots to learn about both TS and typing but I totally agree with you. 100% typing is hard, takes much time and effort indeed and probably it is not something ideal in most of the cases.

Collapse
 
redbar0n profile image
Magne • Edited

Try extracting the data fetching into a custom hook, for reusability, like shown in here in Approach A: dev.to/suhanw/decouple-data-from-u...

It is essentially what React Query does for you, which I would consider to look into vs Axios. That might reduce the boilerplate code considerably.

PS: The example would have been nice with a non-typescript version of the code, side-by-side. So we can see what headache came because of TypeScript vs. what came because of Axios.

Collapse
 
vishnumohanrk profile image
Vishnu
Collapse
 
vinicius77 profile image
Vinicius Cerqueira Bonifácio

Thanks for commenting, Vishnumohan.

I will surely check it out and also add this link into this article as another reference.

Collapse
 
thesanjeevsharma profile image
Sanjeev Sharma

I started using typescript recently. It frustrates me so much some times but I still love it. Paired with intellisense, it is a life saver.

Collapse
 
vinicius77 profile image
Vinicius Cerqueira Bonifácio

Hi, Sanjeev.

Thanks for commenting. :)

I am also started using it recently and I totally understand your frustration. It is the same as mine. jeje To be honest, my first experience with TS was really good even I have "typed" more than I should as you can notice.

Intellisense is a very nice tool and indeed is a life saver.