2017-07-21 22 views
0

我有一個名爲Profile的嵌套React組件。在整個頁面刷新所有的數據加載正確,但是當我點擊一個鏈接帶我到另一個頁面,如設置,然後導航回配置文件,沒有數據加載。我注意到刷新時,componentWillReceiveProps觸發我的console.log,但是當我使用鏈接時它不會觸發。我想知道這是否是由於我的createContainer沒有正確卸載?嵌套React +流星組件在頁面加載時未收到道具

Profile receives props on full refresh and loads correctly. I navigate to settings and everything works correctly. I navigate back to profile and nothing loads, componentWillReceiveProps is not fired

圖片1:個人資料上完全刷新和載荷接收道具正確。 圖2:我導航到設置,一切正常。 圖3:我導航回到配置文件並且沒有加載,componentWillReceiveProps未被觸發

這些組件是使用反應路由器的嵌套路由。但我很困惑如何設置工作正常,沒有明顯的代碼差異。

任何幫助非常感謝,謝謝!

ProfileContainer.js

import React, { Component } from 'react'; 
import { Meteor } from 'meteor/meteor'; 
import { createContainer } from 'meteor/react-meteor-data'; 
import introJs from 'intro.js'; 
import { browserHistory } from 'react-router'; 
import '../../../../../node_modules/intro.js/introjs.css'; 

// Custom 
import ProfileForm from './ProfileForm'; 
import { countryList, statesList, industryList, incomesList, monthsList, educationsList, ofAgeCheck } from '../../../../modules/helpers.js'; 
import { upsertUserProfile } from '../../../../../imports/api/methods/profile/settingsMethods'; 
import { changeIntroTour } from '../../../../api/methods/user/userMethods'; 

// Collections 
import { UserProfile } from '../../../../api/collections/profile/userProfileCollection'; 
import { IntroTour } from '../../../../api/collections/user/introTourCollection'; 

const expertiseOptions = []; 
const dayOptions = []; 
const yearOptions = []; 

const profileIntro = { 
    text: 'Tell us a little about yourself.', 
}; 
const tourObj = { 
    userId: Meteor.userId(), 
    page: 'profile', 
}; 
class ProfileFormContainer extends Component { 

    constructor() { 
    super(); 
    const NA = 'N/A'; 
    this.state = { 
     firstView: NA, 
     birthmonth: NA, 
     birthday: NA, 
     birthyear: NA, 
     sex: NA, 
     expertise: '', 
     country: '', 
     state: '', 
     industry: '', 
     income: '', 
     education: '', 
     showTour: false, 
     tourRunning: false, 
    }; 
    } 

    componentDidMount() { 
    this.loadExpertiseOptions(); 
    this.loadBirthdateOptions(); 
    this.handleChange = this 
     .handleChange 
     .bind(this); 
    this.upsertToDB = this 
     .upsertToDB 
     .bind(this); 
    } 

    componentWillUnmount() { 
    introJs.introJs().exit(); 
    } 

    componentWillReceiveProps(nextProps) { 
    console.log(nextProps); 
    this.existingSettings(nextProps); 
    if (nextProps.intro.length > 0) { 
     this.setState({ 
     showTour: nextProps.intro[0].profileTour, 
     },() => { 
     if (!this.state.tourRunning) { 
      this.runTour(); 
     } 
     }); 
    } 
    } 

    runTour() { 
    if (this.state.showTour === true) { 
     this.setState({ 
     tourRunning: true, 
     }); 
     introJs.introJs().setOption('doneLabel', 'Next').start().oncomplete(() => { 
     changeIntroTour.call(tourObj); 
     browserHistory.push('/user/settings'); 
     }) 
     .onexit(() => { 
      changeIntroTour.call(tourObj); 
     }); 
    } 
    } 

    handleChange(event) { 
    this.setState({ 
     [event.target.name]: event.target.value, 
    }); 
    } 

    existingSettings(data) { 
    const user = data.profile[0]; 
    this.setState({ 
     birthmonth: user.birthmonth, 
     birthday: user.birthday, 
     birthyear: user.birthyear, 
     sex: user.sex, 
     expertise: user.expertise, 
     country: user.country, 
     state: user.state, 
     industry: user.industry, 
     income: user.income, 
     education: user.education, 
    }); 
    } 

    loadExpertiseOptions() { 
    for (let i = 1; i <= 10; i++) { 
     expertiseOptions.push(
     <option key={ i } value={ i }> 
      { i } 
     </option> 
    ); 
    } 
    } 


    loadBirthdateOptions() { 
    this.loadDayOptions(); 
    this.loadYearOptions(); 
    } 

    loadDayOptions() { 
    dayOptions.push(
     <option key={ ' ' } value={ ' ' }> 
     </option> 
    ); 
    for (let i = 1; i <= 31; i++) { 
     dayOptions.push(
     <option key={ i } value={ i }> 
      { i } 
     </option> 
    ); 
    } 
    } 

    loadYearOptions() { 
    yearOptions.push(
     <option key={ ' ' } value={ ' ' }> 
     </option> 
    ); 
    for (let i = new Date().getFullYear(); i >= 1900; i--) { 
     yearOptions.push(
     <option key={ i } value={ i }> 
      { i } 
     </option> 
    ); 
    } 
    } 

    upsertToDB() { 
    if (ofAgeCheck(13, this.state.birthmonth, this.state.birthday, this.state.birthyear)) { 
     Bert.alert('If you are under 13 years of age, then please do not use the service.', 'danger'); 
    } else if (this.state.birthday === 'N/A' || this.state.birthmonth === 'N/A' || this.state.birthyear === 'N/A' || this.state.sex === 'N/A') { 
     Bert.alert('Please complete all required fields.', 'danger'); 
    } else { 
     const birthdateFormatted = `${this.state.birthmonth}-${this.state.birthday}-${this.state.birthyear}`; 
     const settingsObj = { 
     userId: Meteor.userId(), 
     birthmonth: this.state.birthmonth, 
     birthday: this.state.birthday, 
     birthyear: this.state.birthyear, 
     birthdate: birthdateFormatted, 
     sex: this.state.sex, 
     expertise: this.state.expertise, 
     country: this.state.country, 
     state: this.state.state, 
     industry: this.state.industry, 
     income: this.state.income, 
     education: this.state.education, 
     }; 

     upsertUserProfile.call(settingsObj, (error, response) => { 
     if (error) { 
      Bert.alert('Save unsuccessful.', 'danger'); 
     } else { 
      if (this.state.tourRunning) { 
      changeIntroTour.call(tourObj); 

      browserHistory.push('/user/settings'); 
      } 
      Bert.alert('Save successful!', 'success'); 
     } 
     }); 
    } 
    } 

    render() { 
    const countries = countryList(); 
    const states = statesList(); 
    const industries = industryList(); 
    const incomes = incomesList(); 
    const months = monthsList(); 
    const educations = educationsList(); 

    if (!this.props.ready) { 
     return (
     <div>Loading user profile...</div> 
     ); 
    } 

    return (
     <ProfileForm {...this.state} months={ months } dayOptions={ dayOptions } yearOptions={ yearOptions } expertise={ expertiseOptions } countries={ countries } 
     states={ states } industries={ industries } incomes={ incomes } educations={ educations } handleChange={ this.handleChange } upsertToDB={ this.upsertToDB } 
     profileIntro={ profileIntro } /> 
    ); 
    } 
} 

ProfileFormContainer.PropTypes = { 
    ready: React.PropTypes.bool, 
    profile: React.PropTypes.array, 
}; 

export default createContainer(() => { 
    const userProfile = Meteor.subscribe('userProfile', Meteor.userId()); 
    const introTour = Meteor.subscribe('introTour', Meteor.userId()); 
    return { 
    ready: userProfile.ready(), 
    profile: UserProfile.find({}).fetch(), 
    intro: IntroTour.find({}).fetch(), 
    }; 
}, ProfileFormContainer); 

下面是反應路由器的代碼

<Router history={browserHistory}> 
     <Route name="Home" path="/" component={Main} > 
     <IndexRoute component={Index} onEnter={authenticate} /> 
     <Route name="Asset Allocation" path="/asset-allocation" 
component={AssetAllocation} /> 
     <Route name="Recover Password" path="/recover-password" 
component={RecoverPassword} /> 
     <Route name="Reset Password" path="/reset-password/:token" 
component={ResetPassword} /> 
     <Route name="User" path="/user" component={Profile}> 
      <Route name="About" path="/user/home" component={User} /> 
      <Route name="Profile" path="/user/profile" component= 
{ProfileForm} /> 
      <Route name="Settings" path="/user/settings" component= 
{SettingsForm} /> 
     </Route> 
     </Route> 
     <Route component={Blank}> 
     <Route name="Login" path="/login" component={Login} onEnter= 
{loggedIn} /> 
     <Route name="Signup" path="/signup" component={Signup} onEnter= 
{loggedIn} /> 
     <Route name="Not Found" path="*" component={NotFound} onEnter= 
{notFound} /> 
     </Route> 
    </Router>, 
+0

試試這個。在您的ProfileContainer中添加一個componentWillUnmount方法,並在其中放置一個'console.log(「unmounting」);'行。然後檢查它是否卸載,當你離開它。 –

+0

@KyleRichardson所有組件在離開時都會卸載。 –

+0

嘗試爲youtr生成的數組添加唯一鍵。 –

回答

0

這是從react-router/v3/docs

<Router> 
    <Route path="/" component={App}> 
    <Route path="about" component={About} /> 
    <Route path="inbox" component={Inbox}> 
     <Route path="messages/:id" component={Message} /> 
    </Route> 
    </Route> 
</Router> 

請注意,嵌套路由沒有前導或後接斜線。按照這個慣例,我想你會解決你的問題。

編輯:回覆您的評論。

這是從陣營componentWillReceiveProps文檔:

陣營安裝過程中不會調用初始道具componentWillReceiveProps。如果組件的一些道具可能更新,它只會調用這個方法。調用this.setState通常不會觸發componentWillReceiveProps。

嘗試將您的數據檢索功能移至componentDidMount生命週期掛鉤。

+0

我更新了所有的路由。問題是,當我回到頁面componentWillReceiveProps沒有被解僱,然後導致我的函數加載數據不這些道具是通過我的createContainer/meteor訂閱傳入的,這是否意味着訂閱沒有成功地取消訂閱組件被卸載? –