如何在nextJS中处理useRouter()的异步问题

问题描述

当我点击 Link 中的 PublicMyTeam.js 时 它使用路由器传递 query(=el.group_name)。

// PublicMyTeam.js
<Link href={`/public/${el.group_name}`}>
    <a><h1 className={styles.team_name}>{el.group_name}</h1></a>
</Link>

但是由于useRouter()的异步问题,useEffect()中的[group].js发生了错误

它无法读取 dbService.collection(group)

// [group].js
const router = useRouter()
const { group } = router.query

async function getGroupPlayers() {
  const querySnapshot = await dbService.collection(group).doc('group_data').collection('players').get()
  querySnapshot.forEach(doc => {
    const singlePlayerObject = {
      name: doc.data().name,photoURL: doc.data().photoURL,joined_date: doc.data().joined_date,rating: doc.data().rating,game_all: doc.data().game_all,game_win: doc.data().game_win,game_lose: doc.data().game_lose,status: doc.data().status,introduce: doc.data().introduce
    }
    setGroupPlayers(groupPlayers => [...groupPlayers,singlePlayerObject])
  })
  groupPlayers.sort((a,b) => b.rating - a.rating)
}

useEffect(() => {
  getGroupPlayers()
},[])

我该怎么办?

解决方法

您可以尝试将整个异步函数的内容放在 useEffect 中,并使函数自调用

    useEffect(() => {
        (async function Update() {
            return (await page.current) === reviews_page
                ? true
                : set_reviews_page((page.current = reviews_page));
        })();
    },[page.current,reviews_page]);

这对于我使用 SWR 配置的自定义分页非常有效。这是我针对同样问题的解决方法

如果你想read up on the topic,它被称为 IIFEs(立即调用的函数表达式)

所以,这样的事情应该可以解决问题:

useEffect(() => {
  (async function getGroupPlayers() {
  const querySnapshot = await dbService.collection(group).doc('group_data').collection('players').get()
  querySnapshot.forEach(doc => {
    const singlePlayerObject = {
      name: doc.data().name,photoURL: doc.data().photoURL,joined_date: doc.data().joined_date,rating: doc.data().rating,game_all: doc.data().game_all,game_win: doc.data().game_win,game_lose: doc.data().game_lose,status: doc.data().status,introduce: doc.data().introduce
    }
    setGroupPlayers(groupPlayers => [...groupPlayers,singlePlayerObject])
  })
  groupPlayers.sort((a,b) => b.rating - a.rating)
 })();
},[])

虽然,您可能希望添加一些条件逻辑以使其按预期执行(以及一两个生命周期依赖项)。使用 useRef 来引用 group 或 groupPlayers,并且只触发生命周期钩子以在 componentDidUpdate 上执行(类似于我在 page.current 和 review_page 值不同时更新状态的方式)。 page.current 是 review_page 状态的 useRef 常量,如下所示:

    const [reviews_page,set_reviews_page] = useState<number>(1);
    const page = useRef<number>(reviews_page);
,

尝试将 router 添加到 useEffect 的依赖项数组,并在调用 router.query.group 之前检查 getGroupPlayers()

useEffect(() => {
    if (router.query.group) {
        getGroupPlayers()
    }
},[router])