2015-07-29 4 views
2

У меня есть компонент-ответчик, и требование заключается в установкеState перед рендером при обновлении (изменение хэша URL-адреса). Ниже приведен фрагмент кода:responsejs setState перед рендерингом при обновлении

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

я это работает, прежде чем я был вызвать этот метод из getInitialState и работает нормально. getInitialState срабатывает только один раз, поэтому я не смог обновить его при изменении URL. Я пробовал различные другие встроенные методы обновления, такие как componentWillReceiveProps, но они на один шаг позади. Кажется, что рендеринг происходит до вызова этого метода. Я также попытался назвать это от render, но, очевидно, состояние запутывается и ломается.

enter image description here

Как показывает этот образ, 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; 
+0

componentWillReceiveProps должен работать перед следующим циклом рендеринга. Не могли бы вы опубликовать немного больше кода, чтобы дать нам лучшее представление о том, что вы делаете? – noveyak

+0

Заметили ли вы, что компонент componentWillReceiveProps даст новое состояние в качестве аргумента, так что это только this.state, что на один шаг назад? – Seppo420

+0

Добавлен код –

ответ

3

КомпонентWillReceiveProps получает новые реквизиты в качестве параметра. Старые реквизиты остаются неизменными при выполнении этого метода, поэтому вам нужно инициализировать свое состояние на основе этого параметра. Попробуйте передать реквизит в качестве параметра к вашему методу componentConfig:

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

Я попробую это и дам вам знать. Спасибо –

+0

Почти работает, но у меня есть проблема, и я хотел бы это понять. currentParamKey не определен в рендере. Любая идея почему? Код обновлен –

+0

Кажется, что вы переопределяете его в методе componentConfig, он объявлен с помощью «var». Итак, ваш глобальный currentParamKey остается неопределенным. Присвойте ему значение в отдельной строке без инструкции var – const314

Смежные вопросы