Utilize the power of TypeScript to display data with impact

Recently, I have been working on a project in TypeScript where I need to fetch data from a URL and display it in my component. Transitioning from JavaScript to TypeScript has been a bit challenging for me. Here is the code snippet I have been working on:

import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";

interface ParamTypes {
  id: string;
}

const SingleProductPage = () => {
  const { id } = useParams<ParamTypes>();
  const [data, setData] = useState();
  const [isLoading, setIsLoading] = useState(false);
  const fetchProduct = async () => {
    setIsLoading(true);
    const response = await fetch(
      "myAPIEndpoint"
    );
    const responseJson = await response.json();
    console.log(await responseJson.response);
    setIsLoading(false);
    setData(await responseJson.response);
  };

  useEffect(() => {
    fetchProduct();
  }, [id]);

  if (isLoading) {
    return <h1>Loading</h1>;
  } else {
    console.log(JSON.stringify(data.landingPageUrl));

    return <h1>Loaded - {data.landingPageUrl}</h1>;
  }
}; 

export default SingleProductPage;

Upon making an API call, the response follows this structure:

{
  "response": {
    "landingPageUrl": "https://google.com",
    "name": "John",
    "Job": {
      "name": "google",
      "designation": "s/w engg"
    }
  }
}

I am specifically interested in displaying the value of landingPageUrl on my page. Additionally, I am looking to destructure the object. In JavaScript, we typically use const { name, id } = data;

Answer №1

To start off, consider adding typings for the state (while not mandatory, it does make things more convenient)

interface jobObjType {
    name: string
    designation: string
}
interface dataType {
    landingPageUrl?: string
    name?: string
    Job?: jobObjType
}
const [data, setData] = useState<dataType>({});

Next, verify how it's progressing:

console.log("data check", data)

and display it as follows:

<h1>Loaded - {data.landingPageUrl||"---"}</h1>

Moreover, there are some errors in your code:

if (isLoading=)

Correct it to:

if (isLoading)

Additionally, how do I destructure the object? In JavaScript, we use const { name, id } = data;

In TypeScript, the process is exactly the same as in JavaScript, but you can also specify types:

const { name, id}: { name: string; id: string} = data

Answer №2

Ensure to specify the type of response in your async function. TypeScript needs to know the expected object type being returned.

Define the response type:

type ApiResponse = {
  "response": {
    "landingPageUrl": string;
    "name": string;
    "Job": {
      "name": string;
      "designation": string;
    }
  }
}

Specify the expected structure for responseJson variable in TypeScript

 const fetchProduct = async () => {
    setIsLoading(true);
    const response = await fetch(
      "myAPIEndpoint"
    );
    const responseJson: ApiResponse = await response.json();
    console.log(await responseJson.response);
    setIsLoading(false);
    setData(await responseJson.response);
  };

Additionally, ensure to declare useState with data

const [data, setData] = useState<IApiResponse["response"] | null>(null);

Use the data in your render after checking for its existence, as initially it might be null or undefined. Avoid destructuring without verifying data presence.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular: ensure the form reverts to its initial value when the modal is closed and reopened

I am facing an issue with my items section. When I click on an item, a modal window opens allowing me to edit the text inside a textarea. However, if I make changes to the text and then cancel or close the modal, upon reopening it, the previously modified ...

Stop const expressions from being widened by type annotation

Is there a way to maintain a constant literal expression (with const assertion) while still enforcing type checking against a specific type to prevent missing or excess properties? In simpler terms, how can the type annotation be prevented from overriding ...

Changing the appearance of a specific child component in React by referencing its id

There is an interface in my code. export interface DefaultFormList { defaultFormItems?: DefaultFormItems[]; } and export interface DefaultFormItems { id: string; name: string; formXml: string, isDefaultFormEnable: boolean; } I am looking ...

What is the best way to set up an endpoint in Angular for image uploading?

Using the Kolkov Angular editor in my Angular application, I have successfully created a rich text editor. Currently, I am looking to upload images from the editor to the server. I already have a function in place that takes a file as an argument and send ...

Feathers.js - Error: Property 'feathers' is missing from the 'Socket' type

Trying to include a property in a socket connection to identify the user and send a response solely to that individual. Came across a potential solution at: How to add parameters to a FeathersJS socket connection Unfortunately, the solution doesn't s ...

"encountered net::ERR_NAME_NOT_RESOLVED error when trying to upload image to s3 storage

I am currently developing an application using Angular. I have been attempting to upload a picture to my S3 bucket, but each time I try, I encounter this error in the console. https://i.stack.imgur.com/qn3AD.png Below is the code snippet from my upload.s ...

What is the best way to have Vue i18n fetch translations from a .json file during Unit Testing?

Previously, with vue-i18n (v8.25.0 and vue v2.6.14), I stored all translations in .ts files containing JS objects: import { LocaleMessages } from 'vue-i18n' const translations: LocaleMessages = { en: { test: 'Test', }, } expor ...

Setting a default check on a checkbox within an ngFor loop in Angular 2

I'm attempting to initialize a default value as checked for a checkbox within my ngFor loop. Here is an array of checkbox items I am working with: tags = [{ name: 'Empathetic', checked: false }, { name: 'Smart money', che ...

Having trouble getting the installed datejs typings to work properly

As I delve into Typescript due to my interest in Angular 2, I have come across the datejs Javascript library. To incorporate it into my Angular 2 project, I went ahead and installed datejs via npm, ensuring that it is correctly listed in my package.json. A ...

What is the recommended data type for the component prop of a Vuelidate field?

I'm currently working on a view that requires validation for certain fields. My main challenge is figuring out how to pass a prop to an InputValidationWrapper Component using something like v$.[keyField], but I'm unsure about the type to set for ...

Leverage the power of forkJoin in JavaScript by utilizing objects or sourcesObject

I'm currently facing an issue with my code snippet below: getInformations().subscribe( informations => { let subs = []; for (const information of informations) { subs.push(getOtherDetails(information.id)); } ...

What is the recommended default value for a file in useState when working with React and TypeScript?

Can anyone help me with initializing a file using useState in React Typescript? const [images, setImages] = useState<File>(); const [formData, setFormData] = useState({ image: File }); I'm facing an issue where the file is sho ...

What is the best way to transfer information from the window method to the data function in a Vue.js application?

Is there a way to transfer information from the window method to the data function in a vuejs component? Take a look at my window method: window.authenticate = function(pid, receiptKey) { console.log("Authentication"); console.log(this) localStorag ...

Tips for utilizing the Axios API client created using the OpenAPITools code generator

Currently, I am utilizing the Swagger/OpenAPI Codegen tool to automatically generate an API client for the Fetch client within my Vue application. However, I have decided that I would prefer to make use of Axios instead. To begin this transition, I initiat ...

Creating a TypeScript schema with nested maps and arrays using Dynamoose

I'm currently in the process of developing a schema for a specific example: { "foods": [ { "fruits": [{ "apple": { "color": "red", ...

Guide to correctly passing custom parameters along with the event object to an asynchronous form submission handler

Asking for guidance on defining and typing custom parameters alongside the native event object in an async onSubmitHandler for a form. The current implementation only receives the native event as a single parameter: const onSubmitHandler: FormEventHa ...

Tips for retrieving data sent through Nextjs Api routing

Here is the API file I have created : import type { NextApiRequest, NextApiResponse } from 'next/types' import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() export default async function handler(req: NextApi ...

TypeScript: "The type is generic and can only be accessed for reading." - Error code 2862

Consider this sample JS function that requires type annotations: const remap = (obj) => { const mapped = {}; Object.keys(obj).forEach((key) => { mapped[key] = !!key; }); return mapped; }; I am attempting to add types using generics (in ...

Bidirectional enumeration in TypeScript

I am working with an enum defined as: enum MyEnum { key1 = 'val1' key2 = 'val2' } However, I am unsure how to create a SomeType implementation that fulfills the following requirements: Function: const myFunction = (param: SomeT ...

When utilizing custom ngDoBootstrap and createCustomElement in Angular, the router fails to recognize the URL being used

WHEN I implement a custom ngDoBootstrap function instead of the default bootstrap: [AppComponent] like shown below: @NgModule({ imports: [ BrowserModule, FormsModule, AppRoutingModule ], declarations: [ AppComponent, HelloComponent ], exports: ...