React useContext 方法

问题描述 投票:0回答:1

我为我的 React 项目创建了一个 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);
}

根布局:

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>
  );
}

现在我的问题是,当我直接访问页面时总是出现以下错误: Error Image

如果我通过按钮访问该页面,它就可以工作。我认为该网站通常是在加载上下文之前加载的。

有什么想法吗?

reactjs next.js react-hooks react-router react-context
1个回答
0
投票
const [data, setData] = useState<AuthorVisibilityInfo | undefined>(undefined);

您的初始状态设置为

undefined
,依此类推,直到数据加载为止,这就是您将提供的内容。

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

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

    return info;
}

但是您也有一些代码在收到未定义时会抛出错误。如果您想保留此未定义的代码,那么您需要设置您的提供程序,使其永远不会使用

undefined
作为其值。

例如,也许您可以更改它提供的值以拥有

loading
变量:

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

然后初始化状态为loading true:

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

然后,一旦数据加载完毕,将其更改为 false,以便任何关心加载完成时间的组件都可以分辨出差异。

setData({
  loading: false,
  ...json
});
© www.soinside.com 2019 - 2024. All rights reserved.