JUNHEE LEE
70
2021-11-25 18:03:02
2
100

리액트 비동기와 state, concat의 관계 질문


깃허브 API를 통해서 제가 사전에 저장한 레포지토리 명을 바탕으로 해당 레포지토리에 해당하는 이슈를 전부 불러오려는 상황입니다.

'keywords'라는 객체 내부에 존재하는 이름을 forEach() 메서드를 통해 각 아이템의 이름을 바탕으로 반복하여 fetchIssue 함수를 호출하고, 결과를 state(issues)에 concat 하려는 로직입니다.


  /* 로컬스토리지에 저장했던 키워드 */
  const [keywords, setKeywords] = useState<keyInterface[]>([])


  /* 패칭한 이슈 */
  const [issues, setIssues] = useState<userRepoIssue[]>([])


  useEffect(() => {
    if (keywords.length) {
      keywords.forEach((keyword, i) => {
        fetchIssue(keyword.name)
      })
    }
  }, [keywords])


  const fetchIssue = useCallback(
    async (name) => {
      setLoading(true)
      try {
        await axios
          .get(`https://api.github.com/repos/${localName}/${name}/issues?perpage=100&sort=created`)
          .then((res) => {
            if (res.status === 200) {
              setIssues(issues.concat(res.data))
            }
          })
      } catch (err) {
        console.error(err)
      }
      setLoading(false)
    },
    [localName, issues]
  )

결과적으로 마지막에 들어온 배열이 기존 채워진 state가 아닌, 빈 객체와 concat 되는 현상이 지속되는데 어떻게 처리할 수 있을까요?

전체 로직은 링크를 걸어두겠습니다 

https://github.com/junh0328/payhere_repo/blob/master/payhere/pages/issues/index.tsx

0
  • 답변 2

  • 오키동키
    119
    2021-11-25 20:42:20
      useEffect( async () => {
        if (keywords.length) {
          keywords.forEach((keyword, i) => {
            await fetchIssue(keyword.name)
          })
        }
      }, [keywords])
    으로 하면 잘 되나요???
  • JUNHEE LEE
    70
    2021-11-25 22:10:11

    자체적으로 고쳐봤는데

    아래 코드처럼 setIssues 로 useState를 관리할 때, concat 이 불변성을 못지켜줘서 새로운 빈 배열이 계속 생성되는 걸로 파악이 되었습니다... ㅋㅋㅋ 그래서 concat 대신에 `...` 연산자를 사용해서 바꿔봤는데 정상적으로 동작하더군요!


    그래도 답변 감사합니다!

      const fetchIssue = useCallback(
        async (name) => {
          setLoading(true)
          try {
            await axios
              .get(`https://api.github.com/repos/${localName}/${name}/issues?perpage=100&sort=created`)
              .then((res) => {
                if (res.status === 200) {
                   setIssues((issues) => [...issues, ...res.data])
                }
              })
          } catch (err) {
            console.error(err)
          }
          setLoading(false)
        },
        [localName, issues]
      )


  • 로그인을 하시면 답변을 등록할 수 있습니다.