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

리액트 비동기와 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

  • 오키동키
    117
    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]
      )


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