假设你有一个Pet组件显示宠物资源。您还拥有通过ownerId属性属于pet的所有者资源。您应该在Pet组件中加载所有者资源吗?
const Pet = React.createClass({
getInitialState() {
return {
pet: PetStore.get(this.props.petId)
};
},
componentDidMount() {
PetStore.addChangeListener(this._onChange);
},
componentWillUnmount() {
PetStore.removeChangeListener(this._onChange);
},
render() {
var owner; // where should I initiate the ajax request to get owner?
return (
<p>{owner.name}</p>
);
},
onChange() {
this.setState({
pet: PetStore.get(this.props.petId)
});
}
});
答案 0 :(得分:1)
正如Thilo所提到的,React文档建议您在componentDidMount
中异步加载数据。在componentDidMount
而不是componentWillMount
上执行此操作的原因是,如果您在服务器上运行React以进行初始页面加载,那么componentWillMount
将会执行,并且您不想在服务器上进行Ajax调用。
话虽如此,我建议您将数据获取逻辑移动到另一个组件(在React世界中通常称为视图控制器)。这意味着您可以使用两个组件,而不是让一个组件同时执行数据获取和渲染。一个是负责获取数据,另一个是渲染数据。您将该数据作为道具传递给视图控制器组件中的渲染组件。一个小例子是:
var Pet = React.createClass({
render() {
return (
<p>Pet: {this.props.pet.name}</p>
<p>Owner: {this.props.owner.name}</p>
);
}
});
var PetController = React.createClass({
getInitialState() {
return {
pet: PetStore.get(this.props.petId),
owner: null
};
},
componentDidMount() {
OwnerStore.getOwner(this.state.pet.ownerId)
.then(owner => this.setState({owner: owner}));
},
render() {
return <Pet pet={this.state.pet} owner={this.state.owner} />;
}
});
这种分离给你的是更简单,更集中的组件。 Pet
组件不必担心从何处获取数据,并且可以在从PetStore
以外的某个位置获取数据的其他情况下重复使用它。 PetController
组件仅关注数据获取和状态管理。为了使Pet
组件更简单,您可以避免在获取所有者之前呈现它。类似的东西:
var PetController = React.createClass({
getInitialState() {
return {
pet: PetStore.get(this.props.petId),
owner: null
};
},
componentDidMount() {
OwnerStore.getOwner(this.state.pet.ownerId)
.then(owner => this.setState({owner: owner}));
},
render() {
if (this.state.pet && this.state.owner) {
return <Pet pet={this.state.pet} owner={this.state.owner} />;
} else {
return <div className="spinner" />;
}
}
});
然后,您的Pet
组件不必担心异步数据提取,因为在数据存在之前它不会被渲染。
答案 1 :(得分:0)
React documentation recommends在componentDidMount
中执行此操作。