繁体   English   中英

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

[英]How to get data from server and use a hook to retrieve it in multiple components?

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

出于某种原因,我遇到了一个无限循环并收到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发出请求 - 为什么不让组件以编程方式执行此操作?

更改getMeuseCallback功能,将其导出:

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 } />

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM