简体   繁体   中英

reactjs setState before render on update

I have a react component and the requirement is to setState before render on update (url hash change). Below is code snippet:

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

I was it working before, I was calling this method from getInitialState and it was working fine. getInitialState fires only once so I was not able to update it on url change. I tried various other inbuilt update methods such as componentWillReceiveProps but they are one step behind. Seems like render happens before this method gets called. I also tried to call it from render but obviously states get confused and it breaks.

在此输入图像描述

As this image demonstrates, componentRillReceiveProps always behind render. I need something that fires before render each time on url update. Hope it makes sense.

or in other words, I would like to fire getInitialState on hash change.

   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;

The componentWillReceiveProps get new props as a parameter. The old props remain unchanged on this method execution, so you need to initialize your state based on this parameter. Try passing the props as a parameter to your componentConfig method:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM