最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - React useContext method - Stack Overflow

programmeradmin4浏览0评论

I created a NewsContext for my React project for accessting static data:

NewsContext:

"use client";

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

export const NewsContext = createContext<AuthorVisibilityInfo | undefined>(undefined);

export function useNewsContext() {
    const info = useContext(NewsContext);

    if (info === undefined) {
        throw new Error("useNewsContext must be used within a NewsProvider");
    }

    return info;
}

export interface AuthorVisibilityInfo {
    visibilities: Visibility[];
    authors: Author[];
}

export interface Visibility {
    name: string;
    displayName: string;
}

export interface Author {
    name: string;
    displayName: string;
    color: string;
}

export const NewsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
    const [data, setData] = useState<AuthorVisibilityInfo | undefined>(undefined);

    useEffect(() => {
        fetch("http://localhost:7070/news/authors-visibility")
            .then(response => {
                if (!response.ok) {
                    throw new Error("Network response was not ok");
                }
                return response.json();
            })
            .then((json: AuthorVisibilityInfo) => {
                console.log("Fetched data:", json);
                setData(json);
            })
            .catch(error => {
                console.error("Error fetching data:", error);
            });
    }, []);

    return (
        <NewsContext.Provider value={data}>
            {children}
        </NewsContext.Provider>
    );
};

export function getAuthorByName(authors: Author[], name: string): Author | undefined {
    return authors.find(author => author.name === name);
}

Root-Layout:

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body
        className="antialiased bg-gray-100 dark:bg-gray-900 dark:text-gray-200 min-h-screen flex flex-col"
      >
        <Header />

        <div className="flex flex-1">
          <div className="flex-1 p-6">
            <NewsProvider>
              {children}
            </NewsProvider>
          </div>
          <Sidebar />
        </div>
        <Footer />
      </body>
    </html>
  );
}

Now my problem is, always when I access directly a page the following error comes up:

If I access the page via a button it is working. I think the site is in general loaded before the context is loaded.

Are there any ideas?

I created a NewsContext for my React project for accessting static data:

NewsContext:

"use client";

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

export const NewsContext = createContext<AuthorVisibilityInfo | undefined>(undefined);

export function useNewsContext() {
    const info = useContext(NewsContext);

    if (info === undefined) {
        throw new Error("useNewsContext must be used within a NewsProvider");
    }

    return info;
}

export interface AuthorVisibilityInfo {
    visibilities: Visibility[];
    authors: Author[];
}

export interface Visibility {
    name: string;
    displayName: string;
}

export interface Author {
    name: string;
    displayName: string;
    color: string;
}

export const NewsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
    const [data, setData] = useState<AuthorVisibilityInfo | undefined>(undefined);

    useEffect(() => {
        fetch("http://localhost:7070/news/authors-visibility")
            .then(response => {
                if (!response.ok) {
                    throw new Error("Network response was not ok");
                }
                return response.json();
            })
            .then((json: AuthorVisibilityInfo) => {
                console.log("Fetched data:", json);
                setData(json);
            })
            .catch(error => {
                console.error("Error fetching data:", error);
            });
    }, []);

    return (
        <NewsContext.Provider value={data}>
            {children}
        </NewsContext.Provider>
    );
};

export function getAuthorByName(authors: Author[], name: string): Author | undefined {
    return authors.find(author => author.name === name);
}

Root-Layout:

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body
        className="antialiased bg-gray-100 dark:bg-gray-900 dark:text-gray-200 min-h-screen flex flex-col"
      >
        <Header />

        <div className="flex flex-1">
          <div className="flex-1 p-6">
            <NewsProvider>
              {children}
            </NewsProvider>
          </div>
          <Sidebar />
        </div>
        <Footer />
      </body>
    </html>
  );
}

Now my problem is, always when I access directly a page the following error comes up:

If I access the page via a button it is working. I think the site is in general loaded before the context is loaded.

Are there any ideas?

Share Improve this question edited Jan 20 at 16:05 Drew Reese 203k17 gold badges234 silver badges266 bronze badges asked Jan 20 at 15:22 Lvkas_Lvkas_ 133 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0
const [data, setData] = useState<AuthorVisibilityInfo | undefined>(undefined);

Your initial state is set to undefined, so on until the data loads, that's what you'll be providing.

export function useNewsContext() {
    const info = useContext(NewsContext);

    if (info === undefined) {
        throw new Error("useNewsContext must be used within a NewsProvider");
    }

    return info;
}

But you also have code that throws an error when it receives undefined. If you want to keep this code that throws on undefined, then you need to set up your provider so it never uses undefined as its value.

For example, maybe you could change the value it provides to have a loading variable:

export interface AuthorVisibilityInfo {
    loading: boolean;
    visibilities: Visibility[];
    authors: Author[];
}

And then initialize the state to have loading true:

const [data, setData] = useState<AuthorVisibilityInfo>({
  loading: true,
  visilibities: [],
  authors: []
});

And then once the data is loaded, change it to false so any component that cares when loading completes can tell the difference.

setData({
  loading: false,
  ...json
});
发布评论

评论列表(0)

  1. 暂无评论