【问题标题】:reactjs setState before render on updatereactjs setState 在更新前渲染
【发布时间】:2015-07-29 13:11:38
【问题描述】:

我有一个反应组件,要求是在更新渲染之前设置状态(url 哈希更改)。下面是代码sn-p:

componentConfig: function() {
   .....
   this.setState({rows: rows});  
   this.setState({loadMoreBtn: loadMoreIsVisible})
},   

我以前是这样工作的,我从getInitialState 调用这个方法,它工作正常。 getInitialState 只触发一次,所以我无法在 url 更改时更新它。我尝试了各种其他内置更新方法,例如componentWillReceiveProps,但它们落后了一步。似乎渲染发生在此方法被调用之前。我也尝试从render 调用它,但显然状态会混淆并且它会中断。

正如这张图片所示,componentRillReceiveProps 总是在渲染后面。我需要在每次更新 url 之前触发的东西。希望这是有道理的。

或者换句话说,我想在哈希更改时触发getInitialState

   var React = require('react'),
    projectsData = require('./../projects'),
    ProjectsRow = require('./projects_row'),
    itemsInRow = 3,
    noOfDefaultRows = 2,
    projects = [],
    currentProjects = [],
    currentPageRows,
    currentParamKey;

var Projects = React.createClass({

    componentWillMount: function() {
        this.componentConfig(this.props);
    }, 

    componentWillReceiveProps: function(nextProps){
        this.componentConfig(nextProps);
    },

    componentConfig: function(props) {
        var rows = [],
            currentParamKey = 'projects',
            loadMoreIsVisible = true,
            i; 

        if(props.params.key) {
            currentParamKey = props.params.key;
        }   

        projects = projectsData.getByKey(currentParamKey);      
        projectsData.currentState[currentParamKey] = noOfDefaultRows;       
        currentProjects = projects.slice(); //Create a copy or array 
        noOfDefaultRows = projectsData.currentState[currentParamKey] || noOfDefaultRows;    

        for (i = 0; i < noOfDefaultRows; i++) {
            if(currentProjects.length) {
                rows.push(currentProjects.splice(0, itemsInRow));
            } 
        }  

        currentProjects.length ? loadMoreIsVisible = true : loadMoreIsVisible = false;

        this.setState({rows: rows});  
        this.setState({loadMoreBtn: loadMoreIsVisible})

        console.log('Finished executing componentConfig and currentParamKey = ' ,currentParamKey);
    },

    loadMoreProjects: function(e) {

        e.preventDefault();
        var addRow = this.state.rows;

        if(currentProjects.length) {
            currentPageRows++;
            addRow.push(currentProjects.splice(0, itemsInRow));
            this.setState({rows: addRow});  
        } 

        if(!currentProjects.length) {
            this.setState({loadMoreBtn: false})
        }   
    },

    render: function() {

        console.log('Now in render and currentParamKey = ' ,currentParamKey);

        var projectUrl;

        //currentParamKey = this.props.params.key;

        if(currentParamKey === 'projects') {
            projectUrl = '#/project';
        } else {
            projectUrl = '#/project/' + currentParamKey
        }   

        return (
            < div className="projects">
                < div className = "jumbotron" >
                    < div className = "container" >
                        < h1 > Projects < /h1> 
                    < /div> 
                < /div>

                < div className = "container" >

                    {this.state.rows.map(function(row, i) {
                        return <ProjectsRow url={projectUrl} row={row} key={i} />
                    }.bind(this))}

                < /div> 

                < div className = "container text-center" > 
                    <a id="loadMore" className= {this.state.loadMoreBtn ? 'linkStyle1' : 'hide'} 
                        onClick = {this.loadMoreProjects}
                        role="button" > <i className="fa fa-angle-down"></i><span>Load More Projects</span> 
                    </a>
                    <br />
                    <br />

                    <div className="contact-me-link">
                        <a className="linkStyle1" href="#/contact">
                            <i className="fa fa-angle-right"></i><span>Contact</span>
                        </a>
                    </div>
                </div>
            < /div>
        );  
    }
});

module.exports = Projects;

【问题讨论】:

  • componentWillReceiveProps 应该在下一个渲染周期之前运行。您能否发布更多代码,让我们更好地了解您在做什么?
  • 你有没有注意到 componentWillReceiveProps 会将新状态作为参数给出,所以只有 this.state 落后了一步?
  • @Seppo420,它需要一个项目数组,具体取决于 url。因此,如果我转到 /xml,然后转到 /html。 /html 将包含 /xml 项目。

标签: javascript reactjs


【解决方案1】:

componentWillReceiveProps 获取新的 props 作为参数。旧的 props 在此方法执行时保持不变,因此您需要根据此参数初始化您的状态。尝试将 props 作为参数传递给您的 componentConfig 方法:

componentWillMount: function() {
    this.componentConfig(this.props);
}, 
componentWillReceiveProps: function(nextProps){
    this.componentConfig(nextProps);
},
componentConfig: function(data) {
    ...
}

【讨论】:

  • 我会试试这个并告诉你。谢谢
  • 几乎工作,但我有一个问题,我想了解它。 currentParamKey 在渲染中未定义。知道为什么吗?代码更新
  • 看来你在componentConfig方法中重新定义了它,它在那里用'var'声明。因此,您的全局 currentParamKey 仍未定义。在没有 var 语句的单独行上为其赋值
猜你喜欢
  • 2016-09-09
  • 2021-12-06
  • 2019-08-04
  • 2018-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-17
  • 2023-03-10
相关资源
最近更新 更多