当我开始在组件内部编写Ajax内容时,我对React世界有点新,并且最近感到困惑。
据我所知,以下是将异步数据呈现到Component中的两种方法,如下所示:
第一种方式:class MyComponent extends React.Component
{
render() {
this.props.userList.map((userInfo) => (<span>{userInfo.name}</span>));
// proceed to render userList
}
}
//userAjaxSelect is a customized selector based on the Reselect lib
//ajax operation happens here!!
const mapStateToProps = (state, props) => {
return {
userList:userAjaxSelect(state, props)
}
}
const mapDispatchToProps = null;// mapDispatchToProps is omitted here
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
第二种方式:
export default class MyComponent extends React.Component
{
componentDidMount() {
//FetchUserList is a redux ActionCreator and omitted here
//it dispatches redux action
//To get ajax response and sync to local UI state.
this.setState({userList: FetchUserList(this.props.groupId)})
}
componentWillReceiveProps(nextProps) {
if(nextProps != this.props)
//FetchUserList is a redux ActionCreator and omitted here
//it dispatches redux action
//To get ajax response and sync to local UI state.
this.setState({userList: FetchUserList(nextProps.groupId)})
}
render() {
this.state.userList.map((userInfo) => (<span>{userInfo.name}</span>);
// proceed to render userList
}
}
从我的角度来看,
第一个解决方案:
ajax操作封装在Select中,用于Reselect lib,我认为它很干净,可以使组件性能受益(通过缓存)
第二个解决方案:
这是一个糟糕的吗?因为很多次我被一些文章警告过,不鼓励使用componentWillReceiveProps设置状态(反模式)?而且它实现的方式相对冗长
哪一个是最佳做法或任何其他更好的替代方案?在加载和刷新Ajax数据时
答案 0 :(得分:2)
老实说,我从未使用过您展示过的任何方法。根据文档,您可能希望componentDidMount
中有任何AJAX请求,并避免在componentWillReceiveProps
中执行AJAX。
背后的原因是即使没有必要的数据也应该安装你的组件,你不想阻止视图(例如,如果你使用componentWillMount
会发生这种情况)如果请求也需要长。我经常看到的模式如下:
export default class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { isFetching: false, userList: [] };
}
componentDidMount() {
this.setState({ isFetching: true });
// In this case FetchUserList is just a simple AJAX call
// not an action
FetchUserList(this.props.groupId)
.then((data) => {
this.setState({ userList: data, isFetching: false });
});
}
render() {
this.state.userList.map((userInfo) => (<span>{userInfo.name}</span>);
}
}
这不考虑错误处理,但我希望你能得到图片(你可以使用.catch
)。如果您的状态已经填充,您甚至可以阻止发送请求,或者如果数据已经存在则可以避免设置状态等等...
另一方面,如果您使用的是redux
,那么有许多中间件可以像redux-thunk
一样帮助它,或者我创建了一个中间件,也称为redux-slim-async
,它可以减少样板,并且是redux文档中显示的内容和一些其他功能的组合。在一天结束时,请使用您熟悉的内容以及对代码库更有意义的内容。
使用redux
的另一种方法可能是在componentDidMount
内触发异步操作,然后你的组件会监听状态的一部分(mapStateToProps
)对componentWillReceiveProps
感兴趣并对export default class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { userList: [] };
}
componentDidMount() {
// In this case FetchUserList is an Action
FetchUserList(this.props.groupId)
}
componentWillReceiveProps(nextProps) {
if(nextProps != this.props) {
this.setState({ userList: nextProps.propFromStateManager });
}
}
render() {
this.state.userList.map((userInfo) => (<span>{userInfo.name}</span>);
}
}
感兴趣,您可以根据从经理处收到的新道具更新组件的内部状态。你展示的是一种我不推荐的混合物。
componentWillReceiveProps
请注意,仅当您需要根据某些props
更改更新组件的内部状态时才应使用reselect
。我看到fetch
派上用场的场景就是当您想要发送reselect
请求时,无论如何更新状态,然后$ cordova run android
Android Studio project detected
ANDROID_HOME=/Users/User/Library/Android/sdk
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home
studio
Starting a Gradle Daemon (subsequent builds will be faster)
:wrapper
BUILD SUCCESSFUL
Total time: 7.673 secs
Subproject Path: CordovaLib
Subproject Path: app
publishNonDefault is deprecated and has no effect anymore. All variants are now published.
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':CordovaLib'.
> Failed to notify project evaluation listener.
> com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
* Get more help at https://help.gradle.org
BUILD FAILED in 2s
(node:24627) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: /Users/User/Sites/testing/cordova/hello/platforms/android/gradlew: Command failed with exit code 1 Error output:
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':CordovaLib'.
> Failed to notify project evaluation listener.
> com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
* Get more help at https://help.gradle.org
将检查状态是否完全相同,在这种情况下,它可能会阻止重新渲染。否则我不会从选择器发出ajax请求。如果我要跳入你的代码,我永远不会期望在选择器中获取异步调用,这不是它们的用途。
如果您需要澄清,请告诉我,我会更新答案。