Suspense 및 ErrorBoundary를 사용하여 React에서 데이터를 가져오는 방법

데이터를 가져오려는 경우 약속을 처리하므로 세 가지 가능한 시나리오가 있습니다.
  • 약속이 해결되고 성공입니다
  • 약속이 해결되고 실패(ErrorBoundary 구성 요소에서 처리)
  • 약속이 보류 상태에 있습니다(Suspense component에서 처리)

  • 이것이 우리 코드가 높은 수준에서 어떻게 보이는지입니다.

    function App() {
      return (
        <>
        <ErrorBoundary>
          <Suspense fallback={<h1>Loading blog...</h1>}>
            <BlogPost resource={resource1} />
            <Share />
          </Suspense>
          </ErrorBoundary>
        </>
      );
    }
    

    BlogPost 이는 약속의 상태를 읽는 구성 요소입니다.

    function BlogPost({resource:{read}}) {
      const {title,body} = read();
      // ...
    


    여기서 resourcecreateResource 함수에 의해 생성된 객체입니다.

    const resource1=createResource(fetchPosts(0))
    

    createResource의 정의를 살펴보겠습니다.

    function createResource(promise){
        let error,response
        promise.then(r=>response=r).catch(e=>(error=e))
        return {
            read(){
                if(error)throw error
                if(response) return response
                throw promise
            }
        }
    }
    


    보시다시피 read 함수는 약속, 오류를 발생시키거나 성공적인 응답을 반환할 수 있습니다. 약속이 Suspense 구성 요소에 의해 포착되고 대체 소품을 렌더링하는 것과 같습니다. 오류는 ErrorBoundary 구성 요소에 의해 포착되며, 잠시 후에 보게 될 것이며 ErrorScreen 구성 요소를 렌더링합니다. 약속이 성공적으로 해결되면 Suspense의 자식이 렌더링됩니다.

    이것은 ErrorBoundary 구성 요소입니다.

    import {Component} from 'react'
    
    function ErrorScreen({error:{message}}){
        return <div>
            Something went wrong: {message}
            </div>
    }
    
    class ErrorBoundary extends Component{
        state={error:null}
        static getDerivedStateFromError(e){
            return {error:e}
        }
        render(){
            const {children,fallback}=this.props
            const {error}=this.state
            if(error&&!fallback)return <ErrorScreen error={error} />
            if(error)return <fallback error={error} />
            return children
        }
    }
    
    export default ErrorBoundary
    


    보시다시피 Suspense 속성과 유사하게 작동하며 fallback 속성을 수락합니다. 이 경우 기본적으로 ErrorScreen 구성 요소를 렌더링합니다.
    fetchPosts() 함수의 정의를 살펴보겠습니다.

    
      let blogPosts = [
        {
          id: 1,
          title: 'qui est esse',
          body: 'est rerum tempore vitae\nsequi sint nihil reprehenderit'
        },
      ];
    
      export function fetchPosts(id) {
        let post = blogPosts[id];
        return new Promise((resolve) => {
          setTimeout(() => {
            console.log("fetched blogs");
            resolve(post);
          }, 2000);
        });
      }
    


    보시다시피 Promise를 반환합니다.

    완성을 위해 BlogPostShare 구성 요소의 정의를 살펴보겠습니다.

    function Share() {
      useEffect(() => {
        console.log("Effect Share");
    
        return () => {
          console.log("Cleanup Share");
        };
      });
    
      console.log("Render Share");
      return (
        <div>Share:&nbsp;
          <span> twitter</span>
          <span> reddit</span>
        </div>
      )
    }
    
    function BlogPost({resource:{read}}) {
      const {title,body} = read();
    
      useEffect(() => {
        console.log("Effect BlogPost");
        return () => {
          console.log("Cleanup BlogPost");
        };
      });
    
      return (
        <div>
          <h1>Blog Post</h1>
          <h3>{title}</h3>
          <span>{body}</span>
        </div>
      );
    }
    


    다음은 앱을 실행할 때 콘솔에 표시되는 출력입니다.



    보시다시피 반응 18에서 Share 구성 요소는 BlogPost가 준비될 때까지 렌더링되지 않습니다. 모두 Suspense 구성 요소의 하위 항목에 속하기 때문입니다. 대신 react 17을 사용했다면 콘솔의 출력은 다음과 같습니다.



    보시다시피 Promise를 해결하기 전에 먼저 Share 구성 요소를 렌더링한 다음 Promise가 성공적으로 해결된 후 BlogPost 구성 요소를 렌더링합니다.

    좋은 웹페이지 즐겨찾기