如何从服务器获取数据并使用钩子在多个组件中检索数据?



我有一个相当基本的用例:我想在应用程序加载时从服务器获取用户信息,然后使用钩子获取不同组件中的信息。

出于某种原因,我遇到了一个无限循环并得到了Error: Maximum update depth exceeded.getMe被递归调用,直到应用崩溃。 这是正确的钩子行为吗?

这是钩子的相关部分:

export default function useUser () {
const [user, setUser] = useState(null)
const [authenticating, setAuthenticating] = useState(true)
// ...
const getMe = (jwt) => {
console.log('set user')
axios.get(baseURL + endpoints.currentUser, { headers: {
'X-Access-Token': jwt,
'Content-Type': 'application/json'
}}).then(response => {
setUser({
name: response.data.name,
img: response.data.avatar_url
})
})
}
useEffect(() => {
getMe(jwt)
}, [])
return { user, authenticating }
}

这是第一次通话

function App () {
const { user, authenticating } = useUser()
const c = useStyles()
return (
authenticating ? (
<div className={c.wrapper}>
<Loader size={60}/>
</div>
) : (
<div className={c.wrapper}>
<div className={c.sidebar}>
<img className={c.lamp} src={ user ? user.img : lamp } />

我还在路由器组件中调用需要用户

const Routes = () => {
const { user } = useUser()
return (
<Router history={history}>
<Switch>
// ...
<Route
path={pages.login}
render={routeProps => (
user ?
<Redirect to={pages.main}/> :
<Login {...routeProps}/>
)}
/>

你不应该每次调用钩子时都请求服务器,因为它几乎是不必要的。你可以为此使用 Redux 或上下文(对于这种范式,redux 会更好(。 但是,如果您坚持使用此方法,则似乎必须将getMe函数包装在useCallback钩子中,因为每次函数运行时都必须重新呈现。

阅读有关useCallback钩的更多信息:

https://reactjs.org/docs/hooks-reference.html#usecallback

您现在通过自定义钩子中的useEffect发出请求 - 为什么不让组件以编程方式执行此操作?

getMe更改为useCallback函数并将其导出:

export default function useUser () {
const [user, setUser] = useState(null)
const [authenticating, setAuthenticating] = useState(true)
// ...
const getMe = useCallback((jwt) => {
console.log('set user')
axios.get(baseURL + endpoints.currentUser, { headers: {
'X-Access-Token': jwt,
'Content-Type': 'application/json'
}}).then(response => {
setUser({
name: response.data.name,
img: response.data.avatar_url
})
})
}, [])
return { user, authenticating, doFetch: getMe }
}

..并在组件中使用该函数(导入doFetch并在挂载时调用它(,例如:

function App () {
const { user, authenticating, doFetch } = useUser()
const c = useStyles()
useEffect(() => doFetch(), [doFetch])
return (
authenticating ? (
<div className={c.wrapper}>
<Loader size={60}/>
</div>
) : (
<div className={c.wrapper}>
<div className={c.sidebar}>
<img className={c.lamp} src={ user ? user.img : lamp } />

您现在避免了无限循环,您的组件控制了请求逻辑而不是可重用的钩子。

相关内容

  • 没有找到相关文章

最新更新