在 API 服务中访问 React 上下文
Access React context in an API service
在我的 React 应用程序中,我使用 context API 通过 useContext
挂钩存储用户信息:
const AuthContext = createContext<AuthContextType>(null!);
const useAuth = () => useContext(AuthContext);
function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User>();
// Implementations of values
const value = useMemo(() => ({ user, login, logout }), [user]);
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
export { AuthProvider, useAuth };
访问授权信息在组件中一切正常,花花公子:
export default function CoolComponent() {
const auth = useAuth();
if (auth.user) {
// Do something
}
return <div>Hello {auth.user}</div>;
}
问题是我的 jwt-token 存储在用户对象中,我的服务中的 API 调用需要它,但不允许在功能组件之外使用挂钩。我可以巧妙地规避这个问题吗?我能想到的一些事情是在每次调用服务时传递令牌(不是很干)或将令牌保存在 localStorage
中,然后在服务中从那里检索它,但似乎没有必要存储两个不同地方的相同信息?
更新:
现在服务代码:
const baseUrl = environment.apiUrl;
function getToken() {
// This is what I would like to get some help with
}
const headers = {
...(getToken() && { Authorization: `Bearer ${getToken()}` }),
"Content-Type": "application/json",
};
function getAllProjects(): Promise<IProject[]> {
return fetch(`${baseUrl}projects`, {
headers,
}).then((response) => response.json());
}
function createProject(project: CreateProjectDTO): Promise<IProject> {
return fetch(`${baseUrl}projects`, {
method: "POST",
headers,
body: JSON.stringify(project),
}).then((response) => response.json());
}
// + many more
export { getAllProjects, createProject };
在组件中调用服务:
useEffect(() => {
const fetchProjects = async () => {
setIsLoading(true);
try {
const allProjects = await getAllProjects();
setProjects(allProjects);
} catch (error) {
// Handle error
} finally {
setIsLoading(false);
}
};
fetchProjects();
}, []);
React documentation 说你不能在 JavaScript 函数中调用钩子。
你能做什么?
使用自定义挂钩。将函数重命名为 useCreateProject
和 return 您的函数。然后你就可以在你的自定义钩子中调用 useAuth
:
const useCreateProject =() =>{
const {user} = useAuth();
function createProject(project: CreateProjectDTO): Promise<IProject> {
return fetch(`${baseUrl}projects`, {
method: "POST",
headers,
body: JSON.stringify(project),
}).then((response) => response.json());
}
return createProject
}
然后这样称呼它:
const createProject = useCreateProject()
useEffect(() => {
const create = async () => {
setIsLoading(true);
try {
await createProject()
} catch (error) {
// Handle error
} finally {
setIsLoading(false);
}
};
create();
}, []);
但我的建议是将令牌存储在 localStorage
或 cookie 中。当用户刷新页面时,上下文数据将丢失。但是,如果您不是这种情况,您可以继续使用上下文。
在我的 React 应用程序中,我使用 context API 通过 useContext
挂钩存储用户信息:
const AuthContext = createContext<AuthContextType>(null!);
const useAuth = () => useContext(AuthContext);
function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User>();
// Implementations of values
const value = useMemo(() => ({ user, login, logout }), [user]);
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
export { AuthProvider, useAuth };
访问授权信息在组件中一切正常,花花公子:
export default function CoolComponent() {
const auth = useAuth();
if (auth.user) {
// Do something
}
return <div>Hello {auth.user}</div>;
}
问题是我的 jwt-token 存储在用户对象中,我的服务中的 API 调用需要它,但不允许在功能组件之外使用挂钩。我可以巧妙地规避这个问题吗?我能想到的一些事情是在每次调用服务时传递令牌(不是很干)或将令牌保存在 localStorage
中,然后在服务中从那里检索它,但似乎没有必要存储两个不同地方的相同信息?
更新:
现在服务代码:
const baseUrl = environment.apiUrl;
function getToken() {
// This is what I would like to get some help with
}
const headers = {
...(getToken() && { Authorization: `Bearer ${getToken()}` }),
"Content-Type": "application/json",
};
function getAllProjects(): Promise<IProject[]> {
return fetch(`${baseUrl}projects`, {
headers,
}).then((response) => response.json());
}
function createProject(project: CreateProjectDTO): Promise<IProject> {
return fetch(`${baseUrl}projects`, {
method: "POST",
headers,
body: JSON.stringify(project),
}).then((response) => response.json());
}
// + many more
export { getAllProjects, createProject };
在组件中调用服务:
useEffect(() => {
const fetchProjects = async () => {
setIsLoading(true);
try {
const allProjects = await getAllProjects();
setProjects(allProjects);
} catch (error) {
// Handle error
} finally {
setIsLoading(false);
}
};
fetchProjects();
}, []);
React documentation 说你不能在 JavaScript 函数中调用钩子。
你能做什么?
使用自定义挂钩。将函数重命名为 useCreateProject
和 return 您的函数。然后你就可以在你的自定义钩子中调用 useAuth
:
const useCreateProject =() =>{
const {user} = useAuth();
function createProject(project: CreateProjectDTO): Promise<IProject> {
return fetch(`${baseUrl}projects`, {
method: "POST",
headers,
body: JSON.stringify(project),
}).then((response) => response.json());
}
return createProject
}
然后这样称呼它:
const createProject = useCreateProject()
useEffect(() => {
const create = async () => {
setIsLoading(true);
try {
await createProject()
} catch (error) {
// Handle error
} finally {
setIsLoading(false);
}
};
create();
}, []);
但我的建议是将令牌存储在 localStorage
或 cookie 中。当用户刷新页面时,上下文数据将丢失。但是,如果您不是这种情况,您可以继续使用上下文。