이 후크가 1000줄 이상의 비동기 코드를 날려버릴 것이라고 약속합니다.

말장난은 없습니다! ;)

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

    또한 시리즈의 다른 블로그를 확인하는 것을 잊지 마십시오!

    좋은 웹페이지 즐겨찾기