如何处理 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])
当我点击 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])