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;
}
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'번째로 실행 시킨다.
시각적으로 자바스크립트 엔진이 어떻게 구동되는지 보여주는 유용한 사이트