2

When I click the Link in PublicMyTeam.js it passes query(=el.group_name) using router.

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

But because of async problem of useRouter(), an error occured in useEffect() in [group].js.

It can't read 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()
}, [])

What should I do?

juliomalves
  • 42,130
  • 20
  • 150
  • 146
hgJang
  • 83
  • 2
  • 6

2 Answers2

1

you could try putting the contents of the entire async function inside of useEffect and make the function self-invoking

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

this works quite well for custom pagination I have configured with SWR. It's my workaround for the same problem

If you want to read up on the topic, it's referred to as IIFEs (Immediately Invoked Function Expression)

So, something like this should do the trick:

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)
 })();
}, [])

Although, you may want to add some conditional logic for this to execute as intended (and a lifecycle dependency or two). make a useRef to reference group or groupPlayers and only trigger the lifecycle hook to execute on componentDidUpdate (similar to how I have the state updating when the page.current and reviews_page values differ). page.current is the useRef const for the reviews_page state as follows:

    const [reviews_page, set_reviews_page] = useState<number>(1);
    const page = useRef<number>(reviews_page);
Andrew Ross
  • 1,094
  • 7
  • 16
  • 1
    Thank you for replay. :D wow... it's pretty hard. I'll try it later and then ask if I have new questions! – hgJang May 30 '21 at 07:46
1

Try adding router to the useEffect's dependencies array, and check for router.query.group before calling getGroupPlayers().

useEffect(() => {
    if (router.query.group) {
        getGroupPlayers()
    }
}, [router])
juliomalves
  • 42,130
  • 20
  • 150
  • 146