programing

컴포넌트의 Reactjs 비동기 렌더링

goodjava 2023. 3. 11. 08:56

컴포넌트의 Reactjs 비동기 렌더링

ajax 요청이 완료된 후 컴포넌트를 렌더링하고 싶습니다.

아래에 내 코드가 표시됩니다.

var CategoriesSetup = React.createClass({

    render: function(){
        var rows = [];
        $.get('http://foobar.io/api/v1/listings/categories/').done(function (data) {
            $.each(data, function(index, element){
                rows.push(<OptionRow obj={element} />);
            });
           return (<Input type='select'>{rows}</Input>)

        })

    }
});

그러나 나는 나의 ajax 요청의 done 메서드로 렌더링을 반환하기 때문에 아래 오류가 발생합니다.

Uncaught Error: Invariant Violation: CategoriesSetup.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.

렌더링을 시작하기 전에 Ajax 요청이 끝날 때까지 기다리는 방법이 있습니까?

이를 처리하는 방법은 두 가지가 있으며, 데이터를 소유해야 하는 구성 요소와 로드 상태에 따라 선택할 수 있습니다.

  1. Ajax 요청을 부모로 이동하고 구성 요소를 조건부로 렌더링합니다.

    var Parent = React.createClass({
      getInitialState: function() {
        return { data: null };
      },
    
      componentDidMount: function() {
        $.get('http://foobar.io/api/v1/listings/categories/').done(function(data) {
          this.setState({data: data});
        }.bind(this));
      },
    
      render: function() {
        if (this.state.data) {
          return <CategoriesSetup data={this.state.data} />;
        }
    
        return <div>Loading...</div>;
      }
    });
    
  2. 컴포넌트에 Ajax 요청을 보관하고 로드하는 동안 조건부로 다른 작업을 렌더링합니다.

    var CategoriesSetup = React.createClass({
      getInitialState: function() {
        return { data: null };
      },
    
      componentDidMount: function() {
        $.get('http://foobar.io/api/v1/listings/categories/').done(function(data) {
          this.setState({data: data});
        }.bind(this));
      },
    
      render: function() {
        if (this.state.data) {
          return <Input type="select">{this.state.data.map(this.renderRow)}</Input>;
        }
    
        return <div>Loading...</div>;
      },
    
      renderRow: function(row) {
        return <OptionRow obj={row} />;
      }
    });
    

컴포넌트의 비동기 렌더링의 기본적인 예를 다음에 나타냅니다.

import React                from 'react';
import ReactDOM             from 'react-dom';        
import PropTypes            from 'prop-types';

export default class YourComponent extends React.PureComponent {
    constructor(props){
        super(props);
        this.state = {
            data: null
        }       
    }

    componentDidMount(){
        const data = {
                optPost: 'userToStat01',
                message: 'We make a research of fetch'
            };
        const endpoint = 'http://example.com/api/phpGetPost.php';       
        const setState = this.setState.bind(this);      
        fetch(endpoint, {
            method: 'POST',
            body: JSON.stringify(data)
        })
        .then((resp) => resp.json())
        .then(function(response) {
            setState({data: response.message});
        });
    }

    render(){
        return (<div>
            {this.state.data === null ? 
                <div>Loading</div>
            :
                <div>{this.state.data}</div>
            }
        </div>);
    }
}

비동기 상태 관리(Playground)

다음 솔루션은 비동기 상태 관리를 가능하게 하며 올바르게 구현된 경우 HTTP 관련 요건에 사용할 수 있습니다.

요구 사항들

  • 관측 가능한 요소를 소비하는 요소만 재렌더합니다.
  • 관찰 가능한 항목에서 자동으로 구독 및 구독을 취소합니다.
  • 다중 및 공동 관측 가능 데이터를 지원합니다.
  • 로드 상태 제공
  • 심플하고 간단한 구현

예상되는 동작

return (
    <Async select={[names$]}>
        {result => <div>{result}</div>}
    </Async>
);

위의 예시는 관찰 가능한 항목에 등록됩니다.names$의 콘텐츠/자녀Async컴포넌트는 다음에 관찰 가능한 컴포넌트에서 실행되었을 때 재실행되며 현재 컴포넌트는 재실행되지 않습니다.

비동기 컴포넌트

export type AsyncProps<T extends any[]> = { select: { [K in keyof T]: Observable<T[K]> }, children: (result?: any[]) => JSX.Element };
export type AsyncState = { result?: any[] };

export default class Async<T extends any[]> extends Component<AsyncProps<T>, AsyncState> {

    private subscription!: Subscription;

    constructor(props: AsyncProps<T>) {
        super(props);
        this.state = {};
    }

    componentDidMount() {
        this.subscription = combineLatest(this.props.select)
            .subscribe(result => this.setState({ result: result as T }))
    }

    componentWillUnmount() {
        this.subscription.unsubscribe();
    }

    render() {
        return (
            <Fragment>
                {this.props.children(this.state.result)}
            </Fragment>
        );
    }

}

언급URL : https://stackoverflow.com/questions/27192621/reactjs-async-rendering-of-components