我有一个名为Profile的嵌套React组件。在整个页面上刷新所有数据都正确加载,但是当我单击链接将我带到另一个页面(如“设置”),然后导航回“配置文件”时,不会加载任何数据。我注意到在刷新时,componentWillReceiveProps会触发我的console.log,但是当我使用链接时它不会触发。我想知道这是否是由于我的createContainer没有正确卸载?
图1:配置文件在完全刷新时收到道具并正确加载。 图2:我导航到设置,一切正常。 图3:我导航回配置文件并且没有任何加载,componentWillReceiveProps没有被触发
这些组件是使用react路由器的嵌套路由。但我很困惑如何设置工作正常,没有明显的代码差异。
非常感谢任何帮助,谢谢!
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 :(得分: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>
注意嵌套路由没有前导或尾部斜杠。遵循该惯例,我认为您将解决您的问题。
编辑:回复你的评论。
这是来自React componentWillReceiveProps文档:
在安装过程中,React不会使用初始道具调用componentWillReceiveProps。如果某些组件的道具可能会更新,它只会调用此方法。调用this.setState通常不会触发componentWillReceiveProps。
尝试将数据检索功能移至componentDidMount
生命周期挂钩。