React Redux 如何使用 ownProps 路由参数进行分派
我似乎无法弄清楚如何使用路由参数/ ownProps 加载组件/对象,我的配置与 React Redux 应用程序的标准配置基本相同,并且我的操作/减速器工作正常,但对于此组件,数据未预加载。我认为这意味着在定义“用户”对象之前尝试使用它时发生了竞争。我之所以这样认为,是因为它偶尔确实有效 - 它正在经历减速器和 api 调用 - 结果看起来不错。有什么方法我应该先创建一个默认的“用户”对象吗?
路线看起来像
[tld]/user/1234
组件
import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as userActions from '../../actions/userActions';
import User from './User';
class UserPage extends Component{
constructor(props, context){
super(props, context);
}
componentDidMount(){
this.fetchData();
}
fetchData(){
const {userId} = this.props;
const {fetchUser} = this.props.actions;
fetchUser(userId);
}
render(){
// This component when rendered has undefined property exceptions
// though sometimes it works :)
return(<User user={this.props.currentUser} />);
}
}
function mapStateToProps(state, ownProps){
return {
currentUser: state.user,
userId: ownProps.params.id
}
}
function mapDispatchToProps(dispatch){
return {
actions: bindActionCreators(userActions, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(UserPage);
更新 所以我想出了一个丑陋的方法在渲染中解决这个问题
return (
{Object.keys(this.props.currentUser).length > 0 ?
<User user={this.props.currentUser} /> ? null }
)
这不可能是正确的方法。 - 我还注意到,如果我只是改变路线 ID,在等待 api 调用返回新用户的延迟时,之前加载的用户会短暂闪现...抱歉,react/redux 对我来说还很新
有几种方法可以避免未定义的 props:
1 在 user Reducer 中定义初始状态
const initialState = { user:'', ... };
const user = (state = initialState, action) => {...};
export default user;
2
使用
state.user||""
const mapStateToProps = (state, ownProps) =>({
currentUser: state.user||"",
userId: ownProps.params.id
});
3 有时需要在数据加载之前不允许挂载组件。
const LoadingBlock = props => {
return (<div>{props.isLoading ? 'loading...' : props.children}</div>);
};
LoadingBlock.defaultProps = {
isLoading: true
};
///then wrap component that will be loading
<LoadingBlock isLoading={this.props.isLoading}>
<UserComponent user={this.props.user}>
</LoadingBlock>
4 如果 this.props.user 未定义,则不显示 userComponent
render(){
let {user} = this.props
return(
<div>{user && <UserComponent user={user}>}</div>
)
}
5 如果 this.props.user 不是未定义,则显示组件,否则显示一些“内容”
render(){
let {user} = this.props
return(
<div>{user ? <UserComponent user={user}> : "loading"}</div>
)
}
6 定义默认值道具
class Control extends React.Component {...}
Control.defaultProps = {value: "somevalue"};
我能想到的几件事:
-
检查
this.props.currentUser
是否已定义实际上是一个好主意,但我会使用以下语法:const { currentUser } = this.props; return currentUser && <User user={currentUser} />;
-
仅当组件添加到 DOM 时才会调用 componentDidMount。因此,如果 UserPage 组件已在 DOM 中,它将不会触发,并且您的获取代码将永远不会被调用。在这种情况下,您可以使用
componentWillReceiveProps
事件来评估新的 props。 (有关更多信息,请参阅: https://facebook.github.io/react/docs/component-specs.html ) -
fetchUser
到底是做什么的?我假设它是一个异步调用来获取用户数据。您是否使用了一些中间件,例如 redux-thunk?该代码看起来怎么样? 如果您使用 Thunk,则可以分派多个操作来指示获取的状态。因此,如下所示:export function fetchUser(userId) { return dispatch => { dispatch(fetchUserStart()); someService.fetchUser(userId) .then(user => dispatch(fetchUserDone(user))) .catch(error => { dispatch(fetchUserError(error)); }); }; }
在上面的代码中,
fetchUserStart
、fetchUserDone
和fetchUserError
都是影响用户状态的操作(此处未显示代码)。fetchUserStart
可以将用户状态设置为未定义,而fetchUserDone
将其设置为您从异步获取中获得的用户。由于您的 UserPage 组件与此状态相连,它将通过显示/不显示用户组件做出反应。