如何在 React 的纯函数组件中处理 Ajax?
How to handle Ajax in pure function components in react?
我试图将所有组件编写为纯函数,但现在我 运行 遇到了麻烦。我有一个看起来有点像下面的组件。麻烦的是,ajax 请求的结果会导致重新呈现,这会导致另一个 ajax 请求,然后就会出现无限循环。如何正确处理?
const PageProductFunnel = function (props) {
const agent = ajaxagent;
var list = [];
agent.get(`https://mylist.com/${productSKU}`).then((res) => {
list = res.data;
});
return (
<div>
<div className="cell">
<article className="article">
<h1 className="article-title">{product.name}</h1>
<FunnelStep {...props} list={list} />
<ButtonAddToCart product={product} />
</article>
</div>
</div>
);
};
您可以采用以下几种方法:
- 全局获取异步数据,而不是在组件的内部呈现
- 不要为此组件使用纯函数,并将异步挂接到生命周期方法中
您需要为此使用 stateful
个组件。
class PageProductFunnel extends React.Component {
state = {
"list": []
}
componentWillMount () {
agent.get(`https://mylist.com/${productSKU}`).then((res) => {
this.setState({list:res.data})
});
}
render () {
return (
<div>
<div className="cell">
<article className="article">
<h1 className="article-title">{product.name}</h1>
<FunnelStep {...props} list={this.state.list} />
<ButtonAddToCart product={product} />
</article>
</div>
</div>
);
}
};
编辑 请阅读评论。经过更多考虑,我决定实施 Davorin Ruševljans 的第一个建议。我自己的解决方案有效,但他的更好。
感谢您的建议,但确实没有解决问题。到目前为止,我所有的代码都是纯净的,我真的很想坚持下去。在我的情况下,在全局级别进行调用不会改变任何内容,因为响应仍会导致渲染。
我更改了代码,使列表成为状态的一部分(我正在使用 redux)。仅当列表为空时,我才执行 ajax 调用。每当我知道需要新数据时,我都会在页面再次呈现之前清除旧列表。
if (props.list.length === 0) {
agent.get(`https://mylist.com/${productSKU}`).then((res) => {
props.setList(res.data);
});
}
执行 ajax 调用的更好的生命周期挂钩是 componentDidMount()。如果你特别想使用纯组件,你也可以在纯组件中使用。
class Sample extends PureComponent{
//react implement ShouldComponentUpdate for us which does shallow comparison
componentDidMount(){
//api call here
}
}
但是你不能只使用 pureComponent 构建一个 React 应用程序,因为如果你不想通过检查状态来停止更新生命周期,那么你不能使用 PureComponent 因为纯组件只为我们做浅层检查,它检查组件中的所有状态。
我们应该在项目中平衡stateful、PureComponent、Stateless。
我试图将所有组件编写为纯函数,但现在我 运行 遇到了麻烦。我有一个看起来有点像下面的组件。麻烦的是,ajax 请求的结果会导致重新呈现,这会导致另一个 ajax 请求,然后就会出现无限循环。如何正确处理?
const PageProductFunnel = function (props) {
const agent = ajaxagent;
var list = [];
agent.get(`https://mylist.com/${productSKU}`).then((res) => {
list = res.data;
});
return (
<div>
<div className="cell">
<article className="article">
<h1 className="article-title">{product.name}</h1>
<FunnelStep {...props} list={list} />
<ButtonAddToCart product={product} />
</article>
</div>
</div>
);
};
您可以采用以下几种方法:
- 全局获取异步数据,而不是在组件的内部呈现
- 不要为此组件使用纯函数,并将异步挂接到生命周期方法中
您需要为此使用 stateful
个组件。
class PageProductFunnel extends React.Component {
state = {
"list": []
}
componentWillMount () {
agent.get(`https://mylist.com/${productSKU}`).then((res) => {
this.setState({list:res.data})
});
}
render () {
return (
<div>
<div className="cell">
<article className="article">
<h1 className="article-title">{product.name}</h1>
<FunnelStep {...props} list={this.state.list} />
<ButtonAddToCart product={product} />
</article>
</div>
</div>
);
}
};
编辑 请阅读评论。经过更多考虑,我决定实施 Davorin Ruševljans 的第一个建议。我自己的解决方案有效,但他的更好。
感谢您的建议,但确实没有解决问题。到目前为止,我所有的代码都是纯净的,我真的很想坚持下去。在我的情况下,在全局级别进行调用不会改变任何内容,因为响应仍会导致渲染。
我更改了代码,使列表成为状态的一部分(我正在使用 redux)。仅当列表为空时,我才执行 ajax 调用。每当我知道需要新数据时,我都会在页面再次呈现之前清除旧列表。
if (props.list.length === 0) {
agent.get(`https://mylist.com/${productSKU}`).then((res) => {
props.setList(res.data);
});
}
执行 ajax 调用的更好的生命周期挂钩是 componentDidMount()。如果你特别想使用纯组件,你也可以在纯组件中使用。
class Sample extends PureComponent{
//react implement ShouldComponentUpdate for us which does shallow comparison
componentDidMount(){
//api call here
}
}
但是你不能只使用 pureComponent 构建一个 React 应用程序,因为如果你不想通过检查状态来停止更新生命周期,那么你不能使用 PureComponent 因为纯组件只为我们做浅层检查,它检查组件中的所有状态。
我们应该在项目中平衡stateful、PureComponent、Stateless。