Javascript ReactJS组件应该在什么时候进行AJAX调用以从道具更新状态?
我有一个React组件,它显示有关实体的信息。实体的id通过属性传入。组件在“componentDidMount”中启动一个AJAX调用,以获取实体,并在调用完成/失败时更新状态 除了在实体id更改时(通过道具),组件不会获取新数据外,这一切都很好 我尝试过在“componentWillReceiveProps”中启动一个调用,但在那个阶段,组件仍然设置了旧的属性。我必须将nextrops传递给AJAX调用方法,这似乎不正确Javascript ReactJS组件应该在什么时候进行AJAX调用以从道具更新状态?,javascript,ajax,reactjs,Javascript,Ajax,Reactjs,我有一个React组件,它显示有关实体的信息。实体的id通过属性传入。组件在“componentDidMount”中启动一个AJAX调用,以获取实体,并在调用完成/失败时更新状态 除了在实体id更改时(通过道具),组件不会获取新数据外,这一切都很好 我尝试过在“componentWillReceiveProps”中启动一个调用,但在那个阶段,组件仍然设置了旧的属性。我必须将nextrops传递给AJAX调用方法,这似乎不正确 让组件异步更新其状态以响应属性更改的最佳/最干净的方法是什么?我也是新
让组件异步更新其状态以响应属性更改的最佳/最干净的方法是什么?我也是新手,所以Flux体系结构对我来说有点吓人。我完全按照你说的做,使用
componentWillMount
通过AJAX加载初始数据,然后componentWillReceiveProps
和nextrops
在道具更改时再次加载新数据:
var Table = React.createClass({
getInitialState: function() {
return { data: [] };
},
componentWillMount: function(){
this.dataSource();
},
componentWillReceiveProps: function(nextProps){
this.dataSource(nextProps);
},
dataSource: function(props){
props = props || this.props;
return $.ajax({
type: "get",
dataType: 'json',
url: '/products?page=' + props.page + "&pageSize=" + props.pageSize
}).done(function(result){
this.setState({ data: result });
}.bind(this));
},
render: function() {
return (
<table className="table table-striped table-bordered">
<Head />
<Body data={this.state.data}/>
</table>
);
}
});
var Table=React.createClass({
getInitialState:函数(){
返回{data:[]};
},
componentWillMount:function(){
this.dataSource();
},
组件将接收道具:函数(下一步){
this.dataSource(nextProps);
},
数据源:函数(道具){
道具=道具| | this.props;
返回$.ajax({
键入:“获取”,
数据类型:“json”,
url:“/products?page=”+props.page+“&pageSize=“+props.pageSize
}).完成(功能(结果){
this.setState({data:result});
}.约束(这个);
},
render:function(){
返回(
);
}
});
自React v16.3.0()以来,钩子组件willmount
和组件willreceiveprops
已被弃用
当您需要在组件第一次呈现()之后立即加载数据时,AJAX请求应该在componentDidMount
钩子中完成。当您希望在某些道具更改后刷新数据时,必须使用componentdiddupdate
hook
但您必须使用另外三个生命周期挂钩,以避免启动无限循环的请求/更新。假设您希望根据props.category
更改更新帖子列表:
应该有两个属性,状态
和类别
,在组件的构造函数上设置为null李>当前类别
- 需要从新的
更新props.category
李>state.category
用于比较shouldComponentUpdate
和state.category
以确定是否应更新组件李>state.currentCategory
- 需要使用
来确定getSnapshotBeforeUpdate
是否应发出AJAX请求或更改componentDidUpdate
值并完成更新周期状态。currentCategory
import React,{Component,Fragment}来自'React';
从“axios”导入axios;
类Post扩展组件{
建造师(道具){
超级(道具);
此.state={
员额:[],
类别:空,
currentCategory:空
};
this._createMarkup=this._createMarkup.bind();
}
静态getDerivedStateFromProps(props,状态){
if(props.category!==state.category){
返回{
类别:道具类别
};
}
返回null;
}
componentDidMount(){
这是。_fetchData();
}
shouldComponentUpdate(下一步,下一步状态){
返回this.state.currentCategory!==nextState.category;
}
getSnapshotBeforeUpdate(prevProps,prevState){
返回prevState.currentCategory!==prevState.category;
}
componentDidUpdate(prevProps、prevState、dataDidFetch){
//dataDidFetch由getSnapshotBeforeUpdate返回
if(dataDidFetch){
这是我的国家({
currentCategory:this.state.category
});
}否则{
这是。_fetchData();
}
}
_fetchData(){
const category=this.state.category;
get(`/some/api/endpoint?category=${category}`)。然后(posts=>{
这是我的国家({
posts:posts.data
});
});
}
_创建标记(html){
返回{uuuhtml:html};
}
render(){
返回(
{this.state.posts.map(post=>(
))}
);
}
}
导出默认帖子;
我想你选择了最好的时刻。从文档中:使用此(componentWillReceiveProps
)作为一个机会,在调用render()
之前,通过使用this.setState()
更新状态,对道具转换作出反应。可以通过此.props访问旧道具。在此函数中调用this.setState()
,将不会触发其他渲染。另一方面,如果您希望在调用之前更新组件,我认为<>代码>组件-Debug Up/<代码>是您正在寻找的。我建议您考虑集中数据处理,以便更容易管理这些类型的流。然后将从存储区接收到的数据作为道具传递给子组件。@Edo只会将相同的问题推到父组件上。我认为情况并非如此,因为执行该操作的是一个位置(控制器),而不是多个位置。然后,存储(而不是组件)将执行AJAX调用(具有所有ID)并返回所有数据。然后将新数据作为道具传递将触发渲染。当您避免使用通量路径时,这几乎就是要使用的模式。一个重构要考虑在获取数据和渲染数据之间做出明显的分离,这将使ReDead()完全遗忘。
import React, { Component, Fragment } from 'react';
import axios from "axios";
class Post extends Component {
constructor(props) {
super(props);
this.state = {
posts: [],
category: null,
currentCategory: null
};
this._createMarkup = this._createMarkup.bind();
}
static getDerivedStateFromProps(props, state) {
if (props.category !== state.category) {
return {
category: props.category
};
}
return null;
}
componentDidMount() {
this._fetchData();
}
shouldComponentUpdate(nextProps, nextState) {
return this.state.currentCategory !== nextState.category;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
return prevState.currentCategory !== prevState.category;
}
componentDidUpdate(prevProps, prevState, dataDidFetch) {
// dataDidFetch is returned by getSnapshotBeforeUpdate
if (dataDidFetch) {
this.setState({
currentCategory: this.state.category
});
} else {
this._fetchData();
}
}
_fetchData() {
const category = this.state.category;
axios.get(`/some/api/endpoint?category=${category}`).then(posts => {
this.setState({
posts: posts.data
});
});
}
_createMarkup(html) {
return { __html: html };
}
render() {
return (
<Fragment>
{this.state.posts.map(post => (
<article className="post" key={post.id}>
<h2>{post.title.rendered}</h2>
<div dangerouslySetInnerHTML={this._createMarkup( post.content.rendered )} />
<p className="post-link">
<a href="{post.resource_link_url}">{post.resource_link_label}</a>
</p>
</article>
))}
</Fragment>
);
}
}
export default Post;