이 후크가 1000줄 이상의 비동기 코드를 날려버릴 것이라고 약속합니다.
27620 단어 webdevreactjavascriptproductivity
Kent의 Epic React Workshop에서 빌드하는 방법을 배운
useAsync()
후크는 다음과 같습니다.function useSafeDispatch(dispatch) {
const mounted = React.useRef(false)
React.useLayoutEffect(() => {
mounted.current = true
return () => (mounted.current = false)
}, [])
return React.useCallback(
(...args) => (mounted.current ? dispatch(...args) : void 0),
[dispatch],
)
}
const defaultInitialState = {status: 'idle', data: null, error: null}
function useAsync(initialState) {
const initialStateRef = React.useRef({
...defaultInitialState,
...initialState,
})
const [{status, data, error}, setState] = React.useReducer(
(s, a) => ({...s, ...a}),
initialStateRef.current,
)
const safeSetState = useSafeDispatch(setState)
const setData = React.useCallback(
data => safeSetState({data, status: 'resolved'}),
[safeSetState],
)
const setError = React.useCallback(
error => safeSetState({error, status: 'rejected'}),
[safeSetState],
)
const reset = React.useCallback(
() => safeSetState(initialStateRef.current),
[safeSetState],
)
const run = React.useCallback(
promise => {
if (!promise || !promise.then) {
throw new Error(
`The argument passed to useAsync().run must be a promise. Maybe a function that's passed isn't returning anything?`,
)
}
safeSetState({status: 'pending'})
return promise.then(
data => {
setData(data)
return data
},
error => {
setError(error)
return Promise.reject(error)
},
)
},
[safeSetState, setData, setError],
)
return {
isIdle: status === 'idle',
isLoading: status === 'pending',
isError: status === 'rejected',
isSuccess: status === 'resolved',
setData,
setError,
error,
status,
data,
run,
reset,
}
}
export {useAsync}
우리는 후크를 사용하여 아래의
BookInfo
구성 요소를 리팩토링하고 여러 줄의 코드를 날려 보다 우아하고 강력하게 만들 것입니다.💣import * as React from 'react'
import {
fetchBook,
BookInfoFallback,
BookForm,
BookDataView,
ErrorFallback,
} from '../book'
function BookInfo({bookName}) {
const [status, setStatus] = React.useState('idle')
const [book, setBook] = React.useState(null)
const [error, setError] = React.useState(null)
React.useEffect(() => {
if (!bookName) {
return
}
setStatus('pending')
fetchBook(bookName).then(
book => {
setBook(book)
setStatus('resolved')
},
error => {
setError(error)
setStatus('rejected')
},
)
}, [bookName])
if (status === 'idle') {
return 'Submit a book'
} else if (status === 'pending') {
return <BookInfoFallback name={bookName} />
} else if (status === 'rejected') {
return <ErrorFallback error={error}/>
} else if (status === 'resolved') {
return <BookDataView book={book} />
}
throw new Error('This should be impossible')
}
function App() {
const [bookName, setBookName] = React.useState('')
function handleSubmit(newBookName) {
setBookName(newBookName)
}
return (
<div className="book-info-app">
<BookForm bookName={bookName} onSubmit={handleSubmit} />
<hr />
<div className="book-info">
<BookInfo bookName={bookName} />
</div>
</div>
)
}
export default App
나는 suuppperrr 흥분된다, 이것을 해보자!
그러나 계속 진행하기 전에 같은 페이지로 이동합시다.
fetchBook
API에서 데이터를 가져와서 해결에 대한 책 데이터와 거부에 대한 오류를 반환하는 Promise를 생성합니다. BookInfoFallback
는 좋은 로딩 효과를 표시하기 위해 bookName을 허용하는 로더 구성 요소입니다. BookForm
는 사용자로부터 데이터를 가져오는 간단한 양식 구성 요소입니다. BookDataView
는 장부 데이터를 사용자에게 표시하는 멋진 구성 요소입니다. ErrorFallback
오류가 있는 멋진 UI를 표시합니다. 이러한 구성 요소의 구현은 이 블로그의 범위를 벗어나지만 일반적인 내용일 뿐입니다.
도대체 우리 코드는 무엇을 하고 있는 걸까요?
사용자로부터 bookName을 가져 와서 다른 조건에 따라 상태를 설정하는
BookInfo
후크에서 bookData 가져오기를 처리하는 useEffect
구성 요소에 전달하고 성공적인 가져오기 시 BookDataView
렌더링도 처리합니다. , ErrorFallback
실패 시, BookInfoFallback
로드 중.좋아, 내가 방아쇠를 당겼을 수도 있어
"Talk is cheap, show me the code" moment.
import * as React from 'react'
import {
fetchBook,
BookInfoFallback,
BookForm,
BookDataView,
ErrorFallback,
} from '../book'
import useAsync from '../utils';
function BookInfo({bookName}) {
/////////////// Focus from here /////////////////
const {data: book, isIdle, isLoading, isError, error, run} = useAsync()
React.useEffect(() => {
if (!pokemonName) {
return
}
run(fetchPokemon(pokemonName))
}, [pokemonName, run])
if (isIdle) {
return 'Submit a book'
} else if (isLoading) {
return <BookInfoFallback name={bookName} />
} else if (isError) {
return <ErrorFallback error={error}/>
} else if (isSuccess) {
return <BookDataView book={book} />
}
//////////////// To here /////////////////
throw new Error('This should be impossible')
}
function App() {
const [bookName, setBookName] = React.useState('')
function handleSubmit(newBookName) {
setBookName(newBookName)
}
return (
<div className="book-info-app">
<BookForm bookName={bookName} onSubmit={handleSubmit} />
<hr />
<div className="book-info">
<BookInfo bookName={bookName} />
</div>
</div>
)
}
export default App
이제 코드를 더 읽기 쉽게 만들 수 있을 뿐만 아니라 구성 요소가 마운트 해제될 때 디스패치를 호출하지 않음으로써 구성 요소를 더욱 강력하게 만들었습니다. 또한 bookName이 변경되지 않습니다.
하지만 가혹한 우리는 꽤 흔한 일을 수행하기 위해 더 많은 코드를 작성하고 있지 않습니까?
예, 우리는 그 후크를 작성함으로써 이와 같은 비동기 코드를 사용하여 프로젝트 전체에서 여러 구성 요소를 리팩터링할 수 있습니다. 누적 시간 절약, 더 적은 코드 배송 및 높은 신뢰도 향상 측면에서 볼 수 있습니다.
이것은 사용 사례를 보여주는
useAsync()
후크의 첫 번째 부분입니다.다음에서 우리는 후크를 분리하고 각 라인을 설명하고 깔끔한 트릭을 배우면서 처음부터 만들 것입니다.
우리는 또한 3부에서 후크를 테스트할 것입니다. 그 이유는 무엇입니까?
파트 2의 실제 거래에 대해 흥분하십니까? 의견에 말하고 이 기사를 친구들과 공유하고 그들도 흥분시키십시오.
나에 대한 작은 소개, 나는 혁신적이고 품질이 좋은 소프트웨어를 통해 세상을 더 나은 곳으로 만들고 싶습니다.
친숙하게 들리나요?
네, 저는 열렬한 팬입니다. 그는 많은 사람들에게 영감을 줍니다.
이 후크는 Epic React 워크샵 전체에서 광범위하게 사용됩니다. 그의 멋진 과정을 확인하십시오 here .
저도 앞으로 이런 블로그를 통해 배운 내용을 공유할 계획입니다. 앞으로도 계속 연락합시다!
Portfolio
또한 시리즈의 다른 블로그를 확인하는 것을 잊지 마십시오!
Reference
이 문제에 관하여(이 후크가 1000줄 이상의 비동기 코드를 날려버릴 것이라고 약속합니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/harshkc/i-promise-this-hook-will-blow-your-1000-lines-of-async-code-2cao텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)