我为我的 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>
);
}
如果我通过按钮访问该页面,它就可以工作。我认为该网站通常是在加载上下文之前加载的。
有什么想法吗?
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
});