React-실험 : 비동기 통신과 state

최문길·2023년 12월 14일
0

react

목록 보기
6/14

react에서 비동기 함수를 호출 할 때 queue에 제쳐두고 나머지 함수들을 single thread 한다.

상황

늘 궁금했었는데, 요번에 console 파티 해봤다.

비동기 통신을 할 때 비동기 통신 함수안에 setState를 넣어 리렌더링을 시켜줄 때, 리렌더링이 몇번 일어나는지를...

그래서 요번에 무한스크롤 구현을 연습하면서 console party 했다.


비동기통신 함수

// 
const getBooks = async (query, pageNumber) => {
    const response = await axios
      .get('http://openlibrary.org/search.json', { params: {q: query, page: pageNumber,}})
    const data = response.data;
    const books = data.docs.map(doc => doc.title);

    return books;
}

비동기통신 + state 변경을 감싼 함수

  const searchBooks = (query, pageNumber) => {
    setIsLoading(true); 
    // getBooks는 비동기 통신 함수입니다.
    getBooks(query, pageNumber).then(books => { 
      if (pageNumber === 1) {
        setBooks([...new Set(books)])
      } else {
        setBooks(prevBooks => [...new Set([...prevBooks, ...books])])
      }
    }).catch(e => {
      setError(true)
    }).finally(() => {
      setIsLoading(false)
    })
  }

모든걸 감싸고 있는 컴포넌트

검색버튼 누르면 몇번 count 될까??


const getBooks = ()=>{...}

// rendering 몇 번되는지 확인하기위해 컴포넌트 바깥에다가 선언
let renderCount = 0;
                      
const SampleInfinityScroll = () => {
  // rendering 될 때마다 ++ 해주는것으로 일딴 rendering 확인
  renderCount++
  console.log(renderingCount) // 마지막 renderingCount = 2
  const searchBooks = (query, pageNumber) => {
    // setState
    setIsLoading(true);
    
    getBooks(query, pageNumber).then(books => {
      if (pageNumber === 1) {
        // setState
        setBooks([...new Set(books)])
      } else {
        setBooks(prevBooks => [...new Set([...prevBooks, ...books])])
      }
    }).catch(e => {
      setError(true)
    }).finally(() => {
      //setState
      setIsLoading(false)
      
    })
  }
  return ( 
    ...
    <button onClick={searchBooks}>검색</button> // 클릭하면 searchBooks가 실행됩니다.
  )
}

rendering Count가 2가 마지막으로 찍힌다. -> 2번 일어난다.

이유 :
searchBooks에 있는 setIsLoading으로 1번 일어나고,
getBooks에서 통신 끝나고 setBooks + finally의 setIsLoading 으로 batch로 인해 1번 더 일어나므로

그렇다면 비동기 통신 할 때, 순차적으로 data를 받아오고 state 변경을 해줄 까??


const getBooks = ()=>{...}

// rendering 몇 번되는지 확인하기위해 컴포넌트 바깥에다가 선언
let renderCount = 0;
                      
const SampleInfinityScroll = () => {
  
  const[ isLoading, setIsLoading ] = useState(false)
  
  // rendering 될 때마다 ++ 해주는것으로 일딴 rendering 확인
  renderCount++
  
  console.log('renderingCount',renderingCount) // 마지막 renderingCount = 2
  const searchBooks = (query, pageNumber) => {
    
    // searchBooks가 실행될 때 isLoading 값은 reRendering되면서 어떻게 값이 변할까?
    console.log('처음 isLoading', isLoading)
    // setState
    setIsLoading(true);
    
    console.log('중간 isLoading', isLoading)
    
    getBooks(query, pageNumber).then(books => {
      if (pageNumber === 1) {
        console.log('비동기통신안의 isLoading ', isLoading)
        // setState
        setBooks([...new Set(books)])
      } else {
        setBooks(prevBooks => [...new Set([...prevBooks, ...books])])
      }
    }).catch(e => {
      setError(true)
    }).finally(() => {
      //setState
      console.log('비동기 통신 마지막 isLoading', isLoading)
      setIsLoading(false)
    })  
   console.log('마지막 isLoading', isLoading)
  }
  console.log('바깥 isLoading' , isLoading )
  return ( 
    ...
    <button onClick={searchBooks}>검색</button> // 클릭하면 searchBooks가 실행됩니다.
  )
}

콘솔 부분을 확인하면

'처음 isLoading' false
// setIsLoading(true)
'중간 isLoading' false
'마지막 isLoading' false
'renderingCount' 1

'바깥 isLoading' true

'비동기통신안의 isLoading' false
'비동기통신 마지막 isLoading' false
'renderingCount' 2

'바깥 isLoading' false

요약

searchBooks 함수 실행하면, 비동기 통신은 queu로 빼서 제쳐두고 아래로 계속 읽어나가며 실행한다.
좀더 편하게 말하자면

  • 리렌더링 시작 -> 이후 getBooks에 있는 state값 변경으로 리렌더링 다시 시작한다.

자바스크립트는 비동기 통신함수를 만나면 queue로 빼서 제쳐두고 나머지를 다 실행 후, queu에서 끝난 결과 값을 불러온다.
그러므로 콘솔부분에서처럼

비동기 통신 에 있는 setState도 제쳐두고
나머지 state변경값들을 전부 모아서 auto batch를 실행 후 reRendering을 '1' 실행 이후

비동기 통신안에 있는 setState값을 전부 모아서 auto batch 실행으로 reRendering을 '2'번째로 실행 시킨다.




시각적으로 자바스크립트 엔진이 어떻게 구동되는지 보여주는 유용한 사이트

0개의 댓글