bestsource

모든 정보를 가져올 때까지 React 컴포넌트를 렌더링하지 않도록 하려면 어떻게 해야 합니까?

bestsource 2023. 2. 28. 23:38
반응형

모든 정보를 가져올 때까지 React 컴포넌트를 렌더링하지 않도록 하려면 어떻게 해야 합니까?

구성 요소를 렌더링하기 전에 몇 가지 정보를 가져와야 합니다.이 정보는 API에 의해 제공되며 Ajax 호출로 가져옵니다.

컴포넌트를 렌더링하기 전에 10초 정도 기다리려고 하는데 다음과 같이 표시됩니다.

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

약속을 이행한 후에 컴포넌트를 렌더링할 수 있습니까?

/** Page Login */
class Login extends React.Component {

  /**
   * @constructor
   * @param {object} props La fonction super() appelle le parent pour y transmettre ses propriétés
   */
  constructor(props) {
    super(props);

    this.handleFormSubmit = this.handleFormSubmit.bind(this);
  }

  /**
   * Reçoit les valeurs des formulaires
   */
  handleFormSubmit(data) {
    const { dispatch } = this.props;

    dispatch(fetchLoginAuth(data));
  }

  normalRender() {
    return (
      <div id="login-page">
        <div className="container-fluid">
          <div className="row">
            <div className="col-md-2">
              <Link to="/" className="home-link"><img src={BASE_URL + '/assets/img/logo.svg'} alt="Logo" /></Link>
            </div>
          </div>
          <div className="row">
            <div className="col-lg-4 col-lg-offset-4">
              <h1><FormattedMessage {...messages.loginPageTitle} /></h1>
            </div>
          </div>
          {React.cloneElement(this.props.children || <div />, { onSubmit: this.handleFormSubmit, login: this.props.login })}
        </div>
      </div>
    );
  }

  /**
   * Render le component - ReactTransitionGroup
   * @return {JSX} Rend la page Registration
   */
  render() {
    setTimeout(this.normalRender, 10000);
  }
}

리액트 라우터를 갖춘 유니버설라우터인 JSX, redux와 함께 ES6를 사용하고 있습니다.

도와주셔서 정말 감사합니다!

제가 보통 하는 일은 다음과 같습니다.

class Login extends React.Component {
    constructor(props) {
        //IMPLEMENT OTHER JUNK HERE
        this.state = {
            data: null //This is what our data will eventually be loaded into
        };
    }
    componentDidMount() {
        this.loadData();
    }
    loadData() {
        /*LOAD DATA, INSERT BELOW LINE IN CALLBACK FUNCTION
            this.setState({
                data: //LOADED DATA
            });
        */
    }
    render() {
        if (!this.state.data) {
            return <div />
        }

        //WE HAVE DATA, DO A NORMAL RENDER
        return (
            <div id="login-page">
                <div className="container-fluid">
                    <div className="row">
                        <div className="col-md-2">
                            <Link to="/" className="home-link"><img src={BASE_URL + '/assets/img/logo.svg'} alt="Logo" /></Link>
                        </div>
                    </div>
                    <div className="row">
                        <div className="col-lg-4 col-lg-offset-4">
                            <h1><FormattedMessage {...messages.loginPageTitle} /></h1>
                        </div>
                    </div>
                    {React.cloneElement(this.props.children || <div />, { onSubmit: this.handleFormSubmit, login: this.props.login })}
                </div>
            </div>
        );
    }
}

앞으로 일어날 일에 대한 내역은 다음과 같습니다.

  1. 컴포넌트가 로드됩니다.
  2. componentDidMount()가 기동하여 loadData()를 실행합니다.
  3. loadData()는 Ajax 요청을 시작하고 Ajax 요청이 데이터를 반환하기 전에 반환한다. 이는 비동기 데이터 로드를 좋아하기 때문이다.
  4. render()가 실행됩니다.부터this.state.datanullif 블록에 패스하고 있습니다.<div />이 반환됩니다.
  5. Ajax 데이터 로드 완료 및this.setState()콜이 발신되어 강제 재검색이 이루어집니다.
  6. render()가 다시 실행됩니다.부터this.state.data이제 값이 포함되므로 if 블록을 건너뛰고 일반 작업을 렌더링합니다.

편집(2019년 10월 11일):componentWillMount()를 componentDidMount()로 이행했습니다.

항상 React가 렌더링되도록 합니다.

비동기적인 것을 할 때는 로딩 스피너 같은 것을 보여 주세요.

render() {
  <div>
    { this.state.isLoading &&
    <div>Loading.. please wait!</div>
    }
    { !this.state.isLoading &&
    <div>My data has arrived!</div>
    }
  </div>
}

생성자를 사용하여 승인된 답변에 대한 대체 방법입니다.개인적으로 저는 이게 좀 더 깨끗하다고 생각해요.

class Menu extends Component {

state = {}

constructor(props) {
    super(props)
    loadData().then(data =>
        this.setState({data: data})
    )
}

async loadData() {
  //get your data
}

render() {
    if (isEmpty(this.state)) {
        return <div>Loading</div>
    }
    return (
        <div id="site">
            {data}
        </div>
    )
 }

이런 걸 해볼 수 있어요.

/** Page Login */
class Login extends React.Component {
    constructor(props) {
    ...
      this.state = {
        ready: false
      };
    }
    componentWillMount() {
       setTimeout(this.handleLoading, 10000);
    }
    handleLoading() {
      this.setState({ ready: true });
    }
    render() {
       if(!this.state.ready)
         return null;
       return normalRender();
    }
}

렌더링 중단은 해킹으로 보입니다...

플레이스 홀더 서브 컴포넌트를 사용하여 컴포넌트의 일부를 렌더링합니다.그런 다음 Ajax 콜이 종료되면 상태를 변경하고 원래 컴포넌트를 렌더링하는 액션을 실행합니다.

UX도 우아함도 좋을 것 같아요.

프레젠테이션 컴포넌트에서 비동기 함수 콜백을 추적하기 위해 여러 장소에서 동일한 사례를 처리해야 하거나 상태를 사용할 필요가 없는 경우 이러한 문제를 쉽게 해결할 수 있는 방법이 있습니다. react-display를 참조하십시오.

반응 반응 반응기는 후크라고 불리는 후크를 제공한다.usePromise, 샌드박스(장난할 수 있습니다.

import React from "react";
import usePromise from "react-promise";
import "./styles.css";

const prom = new Promise((resolutionFunc, rejectionFunc) => {
  // call your async return values after succesfull response
  setTimeout(function () {
    resolutionFunc(<h1> Hello World </h1>);
  }, 5000);
});
const App = () => {
  const { value, loading } = usePromise(prom);
  if (loading) return <div> loading </div>;
  return <div>{value}</div>;
};
export default App;

조금 늦으면 헬로월드를 볼 수 있어요

언급URL : https://stackoverflow.com/questions/35022922/how-can-i-block-a-react-component-to-be-rendered-until-i-fetched-all-information

반응형