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

how to handle useRouter()s async problem in nextJS

当我点击 PublicMyTeam.js 中的 Link 它通过 query(=el.group_name) 使用 router.

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

但是由于useRouter()的async问题,[group].js中的useEffect()出错了。

无法读取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()
}, [])

我该怎么办?

你可以试试把整个async函数的内容放到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 和 reviews_page 值不同时更新状态的方式)。 page.current 是 reviews_page 状态的 useRef 常量,如下所示:

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

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

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