it-source

async componentDidMount()를 사용하는 것은 좋은 것입니까?

criticalcode 2023. 3. 12. 10:55
반응형

async componentDidMount()를 사용하는 것은 좋은 것입니까?

componentDidMount()비동기 함수의 베스트 프랙티스로서 리액트 네이티브를 사용하지 않는 것이 좋을까요?

가 정보를 좀 요.AsyncStorage마운트되었을 때, 그것을 하게 하는 은, 「이것」을 「이것」으로입니다.componentDidMount()함수 비동기

async componentDidMount() {
    let auth = await this.getAuth();
    if (auth) 
        this.checkAuth(auth);
}

그것에 문제가 있거나 이 문제에 대한 다른 해결책이 있나요?

먼저 차이점을 지적하고 문제를 일으킬 수 있는 방법을 알아봅시다.

sync abycode는 '동기'와 '입니다.componentDidMount()다음 중 하나:

// This is typescript code
componentDidMount(): void { /* do something */ }

async componentDidMount(): Promise<void> {
    /* do something */
    /* You can use "await" here */
}

코드를 보면 다음과 같은 차이를 알 수 있습니다.

  1. async 지나지 않습니다.타이프 스크립트에서는 이것은 단순한 코드 마커입니다.하다
    • 을 강제로 「」로 .Promise<void>void타자기본
    • 해서 사용할 수 있게 해 주세요.await키워드를 지정합니다.
  2. .void로로 합니다.Promise<void>
    • 할 수 이에요: 즉, 음, 다, 다, 다, 다, 다, 다, 다, 다, 다, 다, 다, 다, 다, 다, it it.
      async someMethod(): Promise<void> { await componentDidMount(); }
  3. 해서 '어울리지 않다'를 할 수 되었습니다.await키워드를 지정하고 실행을 일시 정지합니다.하다, 하다, 하다, 하다.

    async componentDidMount(): Promise<void> {
        const users = await axios.get<string>("http://localhost:9001/users");
        const questions = await axios.get<string>("http://localhost:9001/questions");
    
        // Sleep for 10 seconds
        await new Promise(resolve => { setTimeout(resolve, 10000); });
    
        // This line of code will be executed after 10+ seconds
        this.setState({users, questions});
        return Promise.resolve();
    }
    

그럼, 어떻게 문제를 일으킬 수 있을까요?

  1. async이치노
  2. 할 수 없다.componentDidMount() type method to return type (형식)Promise<void>해합니니다다

    이 「」인 .Promise<void> 없이await이 「Return」, 「Return」, 「Calling」인 .void.

  3. 은 사용 후가 componentDidMount()갓차가 요.하지만 거기엔 잡혔어.

    예를 들어 위의 경우this.setState({users, questions});10월 10일...

    this.setState({users: newerUsers, questions: newerQuestions});

    (가) DOM이 되었습니다...이 성공적으로 실행되었고 DOM이 업데이트되었습니다.그 결과는 사용자들에게 보여졌다.열 번된 ★★★★★★★★★★★★★★★★★」this.setState(...)DOM을 사용하다이 시간에는 오래된 사용자와 오래된 질문이 사용됩니다.을 사용하다

=> 꽤 안전합니다 (100%는 잘 모르겠습니다)asynccomponentDidMount()나는 그것의 열렬한 팬이고 지금까지 너무 많은 두통을 일으키는 어떤 문제도 마주치지 않았다.

2020년 4월 갱신:이 문제는 최신 React 16.13.1에서 해결된 것으로 보입니다. 이 샌드박스 예를 참조하십시오.이것을 지적해 주신 @abernier님 덕분입니다.


몇 가지 조사를 해봤는데 중요한 차이점이 하나 있어요.React는 비동기 라이프 사이클 메서드의 오류를 처리하지 않습니다.

그래서 이런 글을 쓰면

componentDidMount()
{
    throw new Error('I crashed!');
}

에러 경계에 의해서 에러가 검출되어 처리되어 그레이스 풀메시지를 표시할 수 있습니다.

코드를 다음과 같이 변경할 경우:

async componentDidMount()
{
    throw new Error('I crashed!');
}

이는 다음과 같습니다.

componentDidMount()
{
    return Promise.reject(new Error('I crashed!'));
}

그러면 당신의 실수는 묵묵히 삼켜질 것입니다.부끄러운 줄 알아, 리액트...

그럼 오류는 어떻게 처리해야 할까요?유일한 방법은 다음과 같은 명시적 어획인 것 같습니다.

async componentDidMount()
{
    try
    {
         await myAsyncFunction();
    }
    catch(error)
    {
        //...
    }
}

또는 다음과 같습니다.

componentDidMount()
{
    myAsyncFunction()
    .catch(()=>
    {
        //...
    });
}

에러가 에러 경계에 도달하는 경우는, 다음의 트릭을 생각할 수 있습니다.

  1. 오류를 파악하여 오류 핸들러가 구성 요소 상태를 변경하도록 합니다.
  2. 있는 는, 를 에러, 에러, 로부터 던집니다.render

예:

class BuggyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { error: null };
  }
  
  buggyAsyncfunction() { return Promise.reject(new Error('I crashed async!'));}
  
  async componentDidMount() {
    try
    {
      await this.buggyAsyncfunction();
    }
    catch(error)
    {
        this.setState({error: error});
    }
  }
  
  render() {
    if(this.state.error)
        throw this.state.error;
        
    return <h1>I am OK</h1>;
  }
}

당신의 코드는 매우 읽기 쉽고 좋습니다.데일 제퍼슨의 기사를 보세요 비동기인이란 걸 보여주죠componentDidMount★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

하지만 어떤 사람들은 코드를 읽는 사람이 리액트가 돌아온 약속으로 뭔가를 한다고 생각할 수도 있다고 말할 것이다.

따라서 이 코드의 해석과 그것이 좋은 관행인지 아닌지는 매우 개인적인 것입니다.

다른 해결책을 원한다면, 약속을 사용할 있습니다.예를 들어 다음과 같습니다.

componentDidMount() {
    fetch(this.getAuth())
      .then(auth => {
          if (auth) this.checkAuth(auth)
      })
}

「 」를 사용하는 componentDidMount 없이async츠키다

componentDidMount()에서 setState()를 즉시 호출할 수 있습니다.추가 렌더링이 트리거되지만 브라우저가 화면을 업데이트하기 전에 실행됩니다.

「 」를 사용하고 async componentDidMount브라우저가 화면을 업데이트한 후 다른 렌더링이 수행됩니다.다만, 데이터의 취득 등, 비동기 사용을 생각하고 있는 경우는, 브라우저의 화면이 2회 갱신되는 것을 피할 수 없습니다.세계에서는 를 PAUSE할 수.

당신이 뭘 하는지 알면 괜찮다고 생각해요. 도 있어요.async componentDidMount()에도 계속 달릴 수 componentWillUnmount가 실행되고 컴포넌트가 마운트 해제되었습니다.

, 동기 태스크와 의 양쪽 .componentDidMount.componentDidMount첫 비동기 코드 에 모든 동기 해야 합니다.모든 동기 코드를 첫 번째 코드보다 먼저 입력해야 합니다.await. 첫 코드 앞에 수 await을 사용하다 는 아마 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.componentDidMount을 사용하다

[ ]를 선택할지 async componentDidMount() 동기 vs 동 vscomponentDidMount(), " "asyncmethods는 컴포넌트 마운트 해제 시 아직 실행 중일 수 있는 리스너 또는 비동기 메서드를 청소해야 합니다.

업데이트:

(내 빌드:반응 16, Web pack 4, Babel 7):

Babel 7을 사용하면 다음과 같은 이점을 얻을 수 있습니다.

이 패턴을 사용하여...

async componentDidMount() {
    try {
        const res = await fetch(config.discover.url);
        const data = await res.json();
        console.log(data);
    } catch(e) {
        console.error(e);
    }
}

다음과 같은 오류가 발생합니다.

수집되지 않은 참조 오류: regeneratorRuntime이 정의되지 않았습니다.

이 경우 babel-plugin-transform-runtime을 설치해야 합니다.

https://babeljs.io/docs/en/babel-plugin-transform-runtime.html

어떤 이유로 위의 패키지(babel-plugin-transform-runtime)를 설치하지 않으려는 경우 Promise 패턴을 고수하십시오.

componentDidMount() {
    fetch(config.discover.url)
    .then(res => res.json())
    .then(data => {
        console.log(data);
    })
    .catch(err => console.error(err));
}

저는 이런 걸 쓰는 게 좋아요.

componentDidMount(){
   const result = makeResquest()
}
async makeRequest(){
   const res = await fetch(url);
   const data = await res.json();
   return data
}

실제로 React는 레거시 라이프 사이클 메서드(componentWillMount, componentWillReceiveProps, componentWillUpdate)에서 벗어나 비동기 렌더링으로 이행하기 때문에 ComponentDidMount에서의 비동기 로딩은 권장되는 설계 패턴입니다.

이 블로그 투고는 이것이 안전한 이유를 설명하고 ComponentDidMount에서의 비동기 로드 예를 제공하는 데 매우 도움이 됩니다.

https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html

@답변에 붙이기 C-F )AsyncMethodErrorHandler를 처리합니다.async componentDidMount()및 기타 비동기 메서드로 인해 오류가 애플리케이션 상태로 버블업되지 않습니다.

maintince를 상속받은 앱에서 수십 개의 비동기 메서드를 try/catch 블록으로 묶는 것보다 쉽다는 것을 알았습니다.

class BuggyComponent extends React.Component<{error_message?:string}> {

  @AsyncMethodErrorHandler("error_message")
  async componentDidMount() {
      await things_that_might_fail();
  }

  render(){
      if(this.state.error_message){
          return <p>Something went wrong: {this.state.error_message}</p>
      }
  }
}


function AsyncMethodErrorHandler(
  /* Key in the this.state to store error messages*/
  key: string,
  /* function for transforming the error into the value stored in this.state[key] */
  error_handler: string | { (e: Error): string } = (e: Error) => e.message
) {

  return function (
    cls: React.Component,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) {
    const f: { (...args: any[]): Promise<any> } = descriptor.value;
    return {
      ...descriptor,
      value: function (...args: any[]) {
        return f.apply(this, args).catch((e: Error) => {
          console.log(`an error occured in the ${propertyKey} Method:`, e);
          (this as any as React.Component).setState({
            [key]:
              typeof error_handler === "string"
                ? error_handler
                : error_handler(e),
          });
        });
      },
    };
  };
}

이 기술에서는, 다음의 이유로, 이 솔루션은 비동기 함수 속성에서는 동작하지 않습니다.

속성 장식기는 클래스에 대해 특정 이름의 속성이 선언되었는지 확인하는 데만 사용할 수 있습니다.

언급URL : https://stackoverflow.com/questions/47970276/is-using-async-componentdidmount-good

반응형