2017-07-21 11 views
0

ProfileというネストされたReactコンポーネントがあります。完全なページリフレッシュでは、すべてのデータが正しく読み込まれますが、リンクをクリックして設定などの別のページに移動した後、プロファイルに戻ると、データは読み込まれません。私はリフレッシュ時に、componentWillReceivePropsが私のconsole.logを起動することに気付きましたが、リンクを使用すると起動しません。これは私のcreateContainerが正しくアンマウントしていないことが原因ですか?ネストされたReact + Meteorコンポーネントがページの負荷で小道具を受け取っていません

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); 

反応ルータコードは、これはreact-router/v3/docsからである

<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

生成された配列に固有のキーを追加してみてください。 –

答えて

0

です。

<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

すべてのルートを更新しました。問題は、コンポーネントのWiredReceivePropsが起動しないページに戻ると、私のcreateContainer/meteorサブスクリプションを介して渡されています。コンポーネントがアンマウントされたときにサブスクリプションがサブスクライブ解除されないことを意味しますか? –

関連する問題