war*_*990 10 javascript reactjs react-hooks
我是 React 新手,我有这个功能。
import Axios from "axios";
const UserService = {
getUserRole: (access_token: string = "") => {
return Axios({
method: "get",
url: "https://<url>/user/role",
headers: {
"Authorization": `Bearer ${access_token}`
}
}).then((response) => {
return response.data;
}).catch((error) => {
console.log(error);
});
}
}
export default UserService
Run Code Online (Sandbox Code Playgroud)
经常被另一个组件使用getUserRole,例如
import UserService from "../../../services/authentication/userService";
import { useAuth } from "react-oidc-context";
...
const auth = useAuth();
UserService.getUserRole(auth.user?.access_token);
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我必须不断地传递access_tokenfrom useAuth。有什么方法可以useAuth在我的内部调用UserService,这样我就不必不断地access_token从我的组件传递?
Emi*_*ron 12
这个问题的前提是向后的,因为我们不应该尝试在 React 之外使用 hooks,而应该在 React 内部使用外部代码。
\n如果角色在各处使用,快速自定义挂钩将帮助您入门。这是包装自定义逻辑的最简单方法,因为钩子旨在包装有状态逻辑以便在组件中重用。
\nimport \xc2\xad{ useState, useEffect } from "react";\nimport { useAuth } from "react-oidc-context";\nimport UserService from "../../../services/authentication/userService";\n\n/**\n * Custom hooks that fetches the roles for the logged in user.\n */\nconst useRoles = () => {\n const auth = useAuth();\n const [roles, setRoles] = useState();\n\n useEffect(() => {\n if (!user) return; // pre-condition\n UserService\n .getUserRole(auth.user.access_token)\n .then(setRoles);\n }, [auth.user]);\n\n return roles;\n}\nRun Code Online (Sandbox Code Playgroud)\n然后在任意组件中:
\nimport useRoles from "../useRoles";\n\nconst MyExampleComponent = () => {\n const roles = useRoles();\n\n if (!roles) return <span>Please login (or something) to see the roles!</span>\n\n return <div>{/* use roles here */}</div>\n}\nRun Code Online (Sandbox Code Playgroud)\n如果用户服务上有很多不同的方法需要在整个应用程序中使用,那么在我看来,包装整个服务并通过React 的上下文提供随时可用的版本将是最好的。
\n但首先,让我们UserService稍微修改一下,以便它使用本地 axios 实例而不是全局 axios 实例。
// I also made it a class, but it would also work with an object.\nclass UserService {\n constructor(axios) {\n this.axios = axios;\n }\n\n getUserRole(){\n // use the local axios instance\n return this.axios({\n method: "get",\n // Use the default URL from local axios instance \n url: "user/role",\n })\n .then(({ data }) => data)\n .catch(console.log),\n }\n\n getSomethingElse() {\n // ...\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n然后,我们可以为用户服务设置 React 的上下文。
\n// UserServiceContext.js\nimport React from \'react\';\nimport { useAuth } from "react-oidc-context";\nimport UserService from "../../../services/authentication/userService";\n\n// Local axios instance\nconst axiosInstance = axios.create({\n baseURL: \'https://<url>\', // set the base URL once here\n});\n\nconst userServiceInstance = new UserService(axiosInstance);\n\nconst UserServiceContext = React.createContext(userServiceInstance);\n\n// Convenience hook\nexport const useUserService = () => useContext(UserServiceContext);\n\nexport const UserServiceProvider = (props) => {\n const auth = useAuth();\n\n useEffect(() => {\n // If the user changes, update the token used by our local axios instance.\n axiosInstance.defaults.headers\n .common[\'Authorization\'] = `Bearer ${auth.user?.access_token}`;\n }, [auth.user]);\n\n return (\n <UserServiceContext.Provider value={userServiceInstance} {...props} />\n ); \n}\nRun Code Online (Sandbox Code Playgroud)\n然后在任何地方,但通常在应用程序的根目录:
\nimport { AuthProvider } from "react-oidc-context";\nimport { UserServiceProvider } from "./UserServiceContext";\n\nconst App = () => (\n <AuthProvider>\n <UserServiceProvider>\n <Content />\n </UserServiceProvider>\n </AuthProvider>\n);\nRun Code Online (Sandbox Code Playgroud)\n现在一切准备就绪,可以在任何组件中使用了!
\nimport { useUserService } from \'../UserServiceContext\';\n\nconst MyExampleComponent = () => {\n const userService = useUserService();\n const [roles, setRoles] = useState();\n\n // e.g. load roles once on mount.\n useEffect(() => {\n userService // use the service from the context\n .getUserRole() // no auth token needed anymore!\n .then(setRoles);\n }, []);\n\n if (!roles) return <span>Please login (or something) to see the roles!</span>\n\n return <div>{/* use roles here */}</div>\n}\nRun Code Online (Sandbox Code Playgroud)\n请注意,自定义挂钩仍可用于包装角色获取逻辑。上下文和钩子可以一起使用,将逻辑包装到每个人自己的偏好中。
\n// Here\'s what the hook could look like if it used the new provider above.\nconst useRoles = () => {\n const userService = useUserService();\n const [roles, setRoles] = useState();\n\n // e.g. load roles once on mount.\n useEffect(() => {\n userService // use the service from the context\n .getUserRole() // no auth token needed anymore!\n .then(setRoles);\n }, []);\n\n return roles;\n}\nRun Code Online (Sandbox Code Playgroud)\n我认为提供者解决方案更好,因为它提供了更大的灵活性,同时保持对公开 API 的控制。
\n在我的解决方案中,我建议使用UserService实例作为提供的值,但可以更改提供程序以仅公开部分 API,或者它可以自动提供角色和其他数据。由你决定!
免责声明:我使用了最少的代码来演示可行的解决方案,我的答案可能无法解决您情况的所有限制。例如, axios 实例可以在提供者内部创建为延迟初始化useRef,实例也是如此UserService,等等。
| 归档时间: |
|
| 查看次数: |
5688 次 |
| 最近记录: |