访问API服务中的React上下文



在我的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。

最新更新