在我的React应用程序中,我使用上下文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-令牌存储在用户对象中,我需要它来调用我的服务中的API,但是钩子不允许在功能组件之外使用。我能巧妙地规避这个问题吗?我能想到的一些事情是在每次调用服务时传递令牌(不是非常DRY)或将令牌保存在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文档说你不能在JavaScript函数中调用钩子。
你能做什么?
使用自定义钩子。将函数重命名为useCreateProject
并返回您的函数。然后你就可以在你的自定义钩子中调用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中。当用户刷新页面时,将丢失上下文数据。但是,如果不是这种情况,您可以继续使用context。