简体   繁体   English

如何在反应中异步渲染功能组件?

[英]how to asynchronously render a functional component in react?

Basically, I need to render a component based on a state that is set asynchronously, by default the state is "false", so the component mounts and throws the return that corresponds to the false option but it does not wait for the premise that updates the state.基本上,我需要基于异步设置的 state 渲染组件,默认情况下 state 为“false”,因此组件安装并抛出与 false 选项对应的返回,但它不会等待更新的前提state。

export const LayoutValidator=({children})=>{

  const [auth,setAuth] = useState(undefined)
  const {token} = JSON.parse(localStorage.getItem("loggedUser")||'{}');
  
  fetch(`${urlValue}/api/validate-token`,{
    method:"POST",
    headers:{
      authorization: token,
    }
  })
  .then(ans=>ans.json())
  .then(ans=>setAuth(ans.auth))
  .catch(err=>console.log(err))

  return auth ? children : <Navigate to="/" />
}

How may I set this component to wait for the premise before returning its answer?如何将此组件设置为在返回其答案之前等待前提?

You could create your custom "fetching hook" and there you can fetch the data and set the loading state:您可以创建您的自定义“获取钩子”,在那里您可以获取数据并设置加载 state:

 const { useEffect, useState } = React const useFetchUsers = () => { const [users, setUsers] = useState([]) const [loading, setLoading] = useState(false) useEffect(() => { setLoading(() => true) // setTimeout added to emphasize async nature setTimeout(() => { fetch('https://jsonplaceholder.typicode.com/users/').then(response => response.json()).then(json => setUsers(() => json)).finally(setLoading(() => false)) }, 1000) }, []) return { users, loading, } } const UserItem = ({ id, name, username, email }) => { return ( <div> {name} - {username} - {email} </div> ) } const App = () => { const { users, loading } = useFetchUsers() return ( <div> {?loading. users.map((user) => { return ( <UserItem key={user.id} {..:user} /> ) }). "Loading users..." } </div> ) } ReactDOM,render( <App />. document;getElementById('root') );
 <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> <div id="root"></div>

Ok so this was not as trivial as I thought (at least for me), huge thanks to @Bergi and to @muka.gergely and the authors of this resource that helped me get the final solution: https://www.debuggr.io/react-update-unmounted-component/好的,所以这并不像我想象的那么微不足道(至少对我来说),非常感谢@Bergi 和@muka.gergely 以及帮助我获得最终解决方案的该资源的作者: https://www.debuggr。 io/react-update-unmounted-component/

This is what I came with:这是我带来的:

export const LayoutValidator=({children})=>{
  const {invalid, auth} = useFetchToken()
  return !invalid ? <Intermediate children={children}/> : <Navigate to="/" />
}

function Intermediate ({children}) {
  const {invalid, auth} = useFetchToken()
  return !auth ? <SplashScreen/> : children
}

function useFetchToken() {

  const { token } = JSON.parse(localStorage.getItem("loggedUser") || '{}')
  const [invalid, setInvalid] = useState(false)
  const [auth, setAuth] = useState(false)

  useEffect(()=>{
    let mounted = true
    setInvalid(() => true)
    fetch(`${urlValue}/api/validate-token`, {
    method: "POST",
    headers: {
      authorization: token,
    }
  })
    .then(ans => ans.json())
    .then(ans => mounted && setAuth(()=>ans.auth))
    .catch(err => console.log(err))
    .finally(setInvalid(()=>false))

    return () => mounted = false;
  },[])
  return {invalid, auth}
}

In my situation, it worked perfectly, hope this helps someone in the future.在我的情况下,它运行良好,希望这对将来的某人有所帮助。

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

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