reactjs我的渲染怎么会被调用很多?

时间:2017-10-26 03:02:47

标签: reactjs

您好我有以下组件

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import RecipeItems from './RecipeItems';

class RecipeContainer extends Component {
    constructor() {
        super();
        this.state = {

        };
    }
    loadRecipe()
    {
        fetch("http://localhost:64755/Api/recipe/" + this.props.recipeId)
        .then(result => {
            return result.json();
        })
        .then(data => {

            //const foo = data;
            this.setState({ Recipe: data })
        }
        )            
        .catch(e => {
            console.log(e)
            return e;
        });
    }
    render() {
        this.loadRecipe()

            console.log('in recipecontainer');
            return(<div></div>)
    }
}

RecipeContainer.propTypes = {
    recipeId: PropTypes.number
};

export default RecipeContainer;

我最初把一个console.log()用于调试,但后来我注意到这个方法正在调用它似乎是一个循环。它不会停止。这有什么不对?我知道当我删除this.setState({Recipe:data})时,循环就会停止。

3 个答案:

答案 0 :(得分:1)

您正在使用fetch方法进行render来电。此调用使用state更新组件的this.setstate,这会触发对render的调用,依此类推。这就是你在循环中看到console.log语句的原因。

您应该在fetch生命周期方法中componentDidMount数据来阻止此类无限循环。只有在componentDidMount第一次完成运行后才会调用render,并且无法进行无限循环的调用。

来自docs

  安装组件后立即调用

componentDidMount()。需要DOM节点的初始化应该放在这里。如果需要从远程端点加载数据,这是实例化网络请求的好地方。

代码:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import RecipeItems from './RecipeItems';

class RecipeContainer extends Component {
    constructor() {
        super();
        this.state = {
            Recipe: null
        };
    }

    componentDidMount(){
        fetch("http://localhost:64755/Api/recipe/" + this.props.recipeId)
        .then(result => {
            return result.json();
        })
        .then(data => {
            this.setState({ Recipe: data });
        })                    
        .catch(e => {
            console.log(e);
            return e;
        });
    }
    render() {    
            console.log('in recipecontainer');
            return(<div></div>);
    }
}

RecipeContainer.propTypes = {
    recipeId: PropTypes.number
};

export default RecipeContainer;

答案 1 :(得分:0)

除了在渲染函数中渲染HTML代码之外,你不应该运行任何东西。因此,将this.loadRecipe移动到componentDidMount函数,看看是否有帮助。

这里也是你的ajax调用的正确语法:

fetch("http://localhost:64755/Api/recipe/" + this.props.recipeId)
    .then(result => {
        this.setState({ Recipe: result.json() })
    })           
    .catch(e => {
        console.log(e);
    });

你也可以在你的班级中设置defultProps,如下所示:

class RecipeContainer extends Component {
    static defaultProps = {
       ...defaultprops
    }

    constructor() {
        super();
        this.state = {

        };
    }
}

答案 2 :(得分:0)

它是一个循环。只要道具或状态发生变化,就会调用render方法。在你的情况下,你正在调用loadRecipe()。更新状态。导致重新执行渲染,再次调用loadRecipe()。所以这将是一个无限循环。你可以在某些生命周期方法中调用loadRecipe。比较componentDidMount()。

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import RecipeItems from './RecipeItems';

class RecipeContainer extends Component {
constructor() {
    super();
    this.state = {

    };
}
componentDidMount(){
  this.loadRecipe() // will be called only once. 
  // thus the state will be updated once by this function.

}
loadRecipe()
{
    fetch("http://localhost:64755/Api/recipe/" + this.props.recipeId)
    .then(result => {
        return result.json();
    })
    .then(data => {

        //const foo = data;
        this.setState({ Recipe: data })
    }
    )            
    .catch(e => {
        console.log(e)
        return e;
    });
}
render() {


        console.log('in recipecontainer');
        return(<div></div>)
       }
   }

RecipeContainer.propTypes = {
    recipeId: PropTypes.number
};

export default RecipeContainer;