Unlocking the Power of useContext in Next.js with TypeScript

I am facing challenges with using useContext to provide data. While I understand how to implement useContext in React, I have been struggling to do the same in Next.js with TypeScript.

Could someone please assist me? Below is my _app.jsx code:

import { AppProps } from 'next/app';
import Head from 'next/head';
import React, { useState } from 'react';
import '../styles/globals.css';

import { CodeContextProvider } from '../shared/context/Context.jsx'

function MyApp({ Component, pageProps }: AppProps): JSX.Element {
    const [context, setContext] = useState("Kyiv");
    return (
        <CodeContextProvider>
            <Head>
                <title></title>
                <link rel="icon" href="/favicon.ico" />
            </Head>
            <Component {...pageProps} />
        </CodeContextProvider>
    )
}

export default MyApp;

My goal is to fetch data from my Node.js backend (already deployed on a Heroku server). I attempted to use useEffect in an external file within useContext but encountered various TypeScript errors.

Here is my Context.jsx file:



import React, { createContext, useState, useEffect } from "react";

const CodeContext = createContext();

const CodeContextProvider = ({ children }) => {
  const [blog, setBlogs] = useState(null);

  useEffect(() => {
    const fetchData = () => {
      fetch(`https://node-test-mongo.herokuapp.com/api/blog`)
      .then((response) => {
          return response.json();
      })
      .then((data) => {
          setBlogs(data.blogs)
      })
    };
    
    fetchData().catch(console.error);
  }, []);

  return (
    <CodeContext.Provider value={blog}>
      {children}
    </CodeContext.Provider>
  );
};

export { CodeContext, CodeContextProvider };


I simply need to retrieve data (title and text) from my API and be able to access it anywhere within my application.

Thank you in advance for any assistance provided. I truly appreciate your help :)

Answer №1

Thanks to @pom421, I was able to resolve the issue at hand. Although I'm still unsure about using Context with TS, I now have a better understanding of how to do it with React Query.

To start off, you need to run npm i react-query@3 to install the third version of the library. Note that the code below will not work with versions 4 and above.

Below is my _app.tsx code:

import { AppProps } from 'next/app';
import Head from 'next/head';
import React, { useState } from 'react';
import '../styles/globals.css';
import { QueryClient, QueryClientProvider } from 'react-query';

const queryClient = new QueryClient({
    defaultOptions: {
        queries: {
            //refetchOnWindowFocus: false //disable refetch everywhere when change page
        },
    },
});

function MyApp({ Component, pageProps }: AppProps): JSX.Element {
    return (
        <QueryClientProvider client={queryClient}>
            <Head>
                <title></title>
                <link rel="icon" href="/favicon.ico" />
            </Head>
            <Component {...pageProps} />
        </QueryClientProvider>
    )
}

export default MyApp;

As you can see, all you need to do is install the library, wrap your code within </QueryClientProvider>, and import the service (a custom file for such cases).

Here's the code for my app.service.ts:

import axios from "axios"

const API_URL = 'https://node-test-mongo.herokuapp.com'

axios.defaults.baseURL = API_URL

export const CryptoService = {
    async getAll() {
        return axios.get('/api/blog')
    }
}

Now we can use our query anywhere in our project, similar to useContext.

Below is the code for my custom <List.tsx /> component:

import { ListProps } from "./List.props";
import styles from "./List.module.css";
import { P } from '../'
import React, { useEffect, useState } from "react";
import { useQuery } from "react-query";
import { CryptoService } from "../../app/services/crypto.service";

export const List = ({ children, className, ...props }: ListProps): JSX.Element => {

    const [blogs, setBlogs] = useState<any[]>([]);

    const { isLoading, data: response, isFetching } = useQuery('crypto', () => CryptoService.getAll())

    return (
        <div

            className={styles.ul}
            {...props}
        >   

            {isLoading ? (
                <div>Loading ...</div>
            ) : response?.data.blogs.length ? (
                <div>
                    {response.data.blogs.map((blog: any) => (
                        <ul key={blog._id}>
                            <li className={styles.li} >
                                <P className={styles.title} size='l'>{blog.title}</P>
                                <P size='l'>{blog.text} </P>
                            </li>
                        </ul>
                    ))}
                    {isFetching && <div className="mt-5">Loading data ...</div>}
                </div>
            ) : (<div>Elements not found ...</div>)}
        </div>
    )
};

I have avoided using both useEffect and useContext with states, which means my application does not automatically update when new elements are added to the backend array.

To address this issue, you could implement something like the following:

import { useQuery } from "react-query";
import { CryptoService } from "../../app/services/crypto.service";

export const Search = ({ className, ...props }: SearchProps): JSX.Element => {


    const { refetch, isFetching } = useQuery('crypto', () => CryptoService.getAll())

    const sendRequest = async () => {
        if (isEncode) {
            const res = await axios.post(`https://node-test-mongo.herokuapp.com/api/blog/encodepost`, {
                title: "Robohamster",
                text: "Its a secret text",
                secretkeyword: "gravityfalls",
            }).catch(err => console.log(err));
        }
        if (!isEncode) {
            const res = await axios.post(`https://node-test-mongo.herokuapp.com/api/blog/decodepost`, {
                text: "fefe",
                secretkeyword: "asfsef",
            }).catch(err => console.log(err));
        }
        console.log("here", inputs);
        refetch(); //this for refetch data 
    }
    return (
        
            <Button
                appearance="ghost"
                className={styles.button}
                onClick={() => sendRequest()}
            >
                Send                //this will send and refresh automatically
            </Button>
    )

}


Therefore, refetch() is an essential function for fetching updated data from the server, functioning similarly to useEffect[].

I hope this information proves helpful to you. Good luck! :)

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

Encountering a Next.js error when attempting to execute code on a live server

Encountering a frustrating error: Failed to compile ./utils/styles.js Error: failed to process internal error: entered unreachable code: assign property in object literal is invalid This annoying error popped up during the build process and can only be res ...

Securely import TypeScript modules from file paths that are dynamically determined during execution

Imagine you have a structure of TypeScript code and assets stored at a specific URL, like between a CDN and a debug location. You want to import the main module and ensure the rest of the structure is imported correctly only when needed, without repeating ...

The 'type' property is not found in the 'Merge<FieldError, FieldErrorsImpl<DeepRequired<any>>>' type, but it is necessary in the 'FieldError' type

I'm currently in the process of developing a Next.js application using TypeScript, TailwindCSS, ReactHookForm, and Yup. The project is coming along smoothly with proper validation and error handling mechanisms in place. However, I've encountered ...

A guide on implementing TypeScript with React Native's platform-specific extensions

The issue at hand: In my react native project, I am using a custom hook that has platform-specific code. I need to import this hook based on the platform in use. When I import it as import useWifi from 'hooks/use-wifi.android';, everything works ...

How can one retrieve data from two distinct API routes within a Next.js application?

Currently, I am working with Next.js and facing a challenge in fetching data from two different API routes simultaneously. My intention is to retrieve this data within the getServerSideProps function. The first dataset that I require can be found at the e ...

Facing issues with the template URL not functioning properly during the migration from Angular 1.5 to Angular 6

I am currently in the process of migrating an Angular 1.5 project to Angular 6, but I've encountered an issue with the templateUrl not working in the Angular 1.5 component. The packages I am using are: Angular CLI 6.0.8 TypeScript 2.7.2 Angular 6.0.7 ...

Utilizing Angular 16 to Link Component Input with Parent Route Parameter

Picture a scenario where there is a component (some.component.ts) in Angular 16 that retrieves the value for its foo property from activeRoute, specifically from the parent route. Take a look at the code snippet below: @Input() foo!: string; constructor(p ...

Can you apply transparency to a hex color variable in SCSS and then use that variable again?

In my app, I have a set of scss variables that represent colors used throughout the interface. For example: $primary-color: #00755E There are also colors that are variations of this primary color with different opacities. For instance, $primary-color with ...

Using TypeScript with React may result in an error message stating that a string cannot be assigned to a parameter of type 'keyof T'

I've encountered an issue with my sorting function that I built using TypeScript and React Hooks. The error message I'm getting is: Argument of type 'string' is not assignable to parameter of type 'keyof T'. Type 'stri ...

Error with Firebase authentication on a Next.js project using TypeScript

I recently started a personal project using Next.js, Typescript, and Firebase for authentication and database management. While working on a sign-in page with Google integration, I encountered an error labeled as auth/argument-error. According to the Fireb ...

An easy way to export static images in Next.js

Whenever I try to export my nextjs app, an error message pops up stating that image export is not supported on static websites. Error: The default image loader in Next.js cannot be used with next export. Possible solutions: - Use next start to run a serv ...

Difficulty Converting Array of Objects to Proper Type with Q.Promise and KO.mapping

I have encountered an issue while trying to filter an observable array. It seems that the ko.utils.arrayFilter method is converting all my model's field names to lowercase, causing unexpected behavior. I should mention that this project involves Types ...

TypeScript - patiently anticipating the completion of nested for loops

Currently, I am working on a task that involves implementing two nested for loops in my code. The primary objective of the first loop is to make an API call, which is dependent on the IDs selected by the user. Unfortunately, the limitation of passing only ...

Struggling to generate a user using the supabase.auth.admin.createUser() function, encountering the error "Failed to create new user due to database error"

While working on my Next.js project, I encountered an issue when trying to create a user using the supabase.auth.admin.createUser() method. The error message I received was: { message: "Database error creating new user" name: "AuthApiE ...

TS2304 error: 'Promise' is nowhere to be found

Hey everyone, I've exhausted all the solutions available on stackoverflow with no luck. So here's my question. tsconfig.json { "version":"2.13.0", "compilerOptions": { "target": "es5", "module": "commonjs", "sourceMap": true, ...

The building process in Next JS is encountering issues because getServerSideProps is not being utilized and there is interference with next

I am currently in the process of developing a web app using Next JS and I must say, the experience has been fantastic so far! In the past, I have utilized CRA for my web app projects, and while the workflow has been similar, there are always new things to ...

Allow access to web application API without requiring an API key

Our team is currently in the process of developing a single-page web application with various components: A NextJS container A Django backend for user management A FastAPI Data API that is secured with API keys and also grants access to third parties The ...

Searching for NavigationEnd events specifically in Angular 12?

When using Angular 11, the following code snippet functions correctly: this.r.events.pipe( filter(event => event instanceof NavigationEnd), map((event: NavigationEnd) => event.url == ROUTES.APPLICATION)) However, when migrating to Angular 12 ...

Angular routing functions flawlessly on Chrome Mac but encounters issues on Chrome iOS

Encountering a strange issue. My routing is properly configured and has been verified multiple times. Oddly enough, page1, page3, and page5 are functioning correctly, while page2, page4, and page6 fail to redirect as expected. Upon clicking the redirect ...

Next.js experiences issues with Material UI upon refreshing the page

Despite following advice from some individuals and adding the babelrc settings in the root directory, Material UI continues to break on refresh in Next.js. Is there a specific configuration setup that needs to be done? applied-styles breaks-on-refresh ...