Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/460.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在获取所有信息之前,如何阻止要渲染的React组件?_Javascript_Reactjs - Fatal编程技术网

Javascript 在获取所有信息之前,如何阻止要渲染的React组件?

Javascript 在获取所有信息之前,如何阻止要渲染的React组件?,javascript,reactjs,Javascript,Reactjs,在渲染我的组件之前,我需要获取一些信息。这些信息将由API提供,并通过ajax调用获取 我正试图在渲染组件之前等待10秒,但它显示: 未捕获不变冲突:Login.render():必须返回有效的组件。您可能返回了未定义、数组或其他无效对象。 我可以在履行承诺后提交我的组件吗 /** Page Login */ class Login extends React.Component { /** * @constructor * @param {object} props La f

在渲染我的组件之前,我需要获取一些信息。这些信息将由API提供,并通过ajax调用获取

我正试图在渲染组件之前等待10秒,但它显示:

未捕获不变冲突:Login.render():必须返回有效的组件。您可能返回了未定义、数组或其他无效对象。

我可以在履行承诺后提交我的组件吗

/** 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);
  }
}
/**页面登录*/
类登录扩展了React.Component{
/**
*@constructor
*@param{object}props La fonction super()将父对象转换为属性
*/
建造师(道具){
超级(道具);
this.handleFormSubmit=this.handleFormSubmit.bind(this);
}
/**
*关于公式的价值
*/
handleFormSubmit(数据){
const{dispatch}=this.props;
调度(获取登录号(数据));
}
normalRender(){
返回(
{React.cloneElement(this.props.children | | |,{onSubmit:this.handleFormSubmit,login:this.props.login}
);
}
/**
*渲染le组件-ReactTransitionGroup
*@return{JSX}Rend la页面注册
*/
render(){
setTimeout(this.normalRender,10000);
}
}
我将ES6与JSX、redux一起使用,这是一个带有react路由器的通用路由器


非常感谢你的帮助

您可以尝试以下方法

/** 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调用完成时,触发一个操作来更改状态并呈现原始组件


在用户体验和优雅度方面都会更好。

始终让React渲染

在执行异步操作时,请显示加载微调器或其他内容

render() {
  <div>
    { this.state.isLoading &&
    <div>Loading.. please wait!</div>
    }
    { !this.state.isLoading &&
    <div>My data has arrived!</div>
    }
  </div>
}
render(){
{this.state.isLoading&&
正在加载..请稍候!
}
{!正在加载此.state.isLoading&&
我的数据已经到了!
}
}

以下是我通常做的事情:

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>
        );
    }
}
类登录扩展了React.Component{
建造师(道具){
//在这里实现其他垃圾
此.state={
data:null//这是我们的数据最终将加载到的内容
};
}
componentDidMount(){
这是loadData();
}
loadData(){
/*加载数据,在回调函数的下行插入
这是我的国家({
数据://加载的数据
});
*/
}
render(){
如果(!this.state.data){
返回
}
//我们有数据,做一个普通的渲染
返回(
{React.cloneElement(this.props.children | | |,{onSubmit:this.handleFormSubmit,login:this.props.login}
);
}
}
下面是将要发生的事情的细目

  • 组件将要加载
  • componentDidMount()激发、运行loadData()
  • loadData()启动ajax请求,在ajax请求返回数据之前返回,因为我们喜欢异步数据加载
  • render()运行。由于
    this.state.data
    null
    ,我们将其传递到if块,并返回
  • Ajax数据加载完成,并进行
    this.setState()
    调用,这将强制重新渲染
  • render()再次运行。由于
    this.state.data
    现在包含一个值,因此我们跳过if块并呈现普通内容

  • 编辑(2019年10月11日):迁移

    使用构造函数替代已接受的答案。我个人觉得这有点干净

    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>
        )
     }
    
    类菜单扩展组件{
    状态={}
    建造师(道具){
    超级(道具)
    loadData()。然后(数据=>
    this.setState({data:data})
    )
    }
    异步加载数据(){
    //获取您的数据
    }
    render(){
    如果(isEmpty(本州)){
    回装
    }
    返回(
    {data}
    )
    }
    
    如果您必须在多个位置处理相同的情况,或者您不必仅仅因为要跟踪表示组件中的异步函数回调而使用state,那么有一种简单的方法可以解决这些问题,请参阅

    react promise提供一个名为
    usePromise
    的钩子(您可以玩)

    从“React”导入React;
    从“反应承诺”中导入usePromise;
    导入“/styles.css”;
    const prom=新承诺((resolutionFunc,rejectionFunc)=>{
    //在成功响应后调用异步返回值
    setTimeout(函数(){
    resolutionFunc(Hello World);
    }, 5000);
    });
    常量应用=()=>{
    const{value,load}=usePromise(prom);
    如果(装载)返回装载;
    返回{value};
    };
    导出默认应用程序;
    

    延迟一段时间后,您可以看到Hello world

    从不阻止渲染。返回null可能会引发错误。渲染空div总是更好。这是错误的:检查:您也可以返回null或false以表示不希望渲染任何内容。在幕后,React渲染标记以使用当前的扩散算法。When返回null或false,ReactDOM.findDOMNode(this)将返回null。Franco Risso:有道理。从我读到的内容来看,最好返回一个空div,但我忘记了它背后的逻辑。@molson504x空div的问题是,您无法知道div是否有默认显示在屏幕上的样式,您可以确定不会显示任何内容.我想要更少的用户界面
    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;