我有一个带有 redux 和 router 的应用程序,在第一次加载时,所有用户都会被加载。为此,我实现了一个主组件,该组件在安装组件时加载用户:
class Content extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
this.props.load();
}
render() {
return this.props.children;
}
}
之后,如果用户选择加载某个用户的详细信息,也会通过相同的 Lifehook 获取详细信息:
class Details extends Component {
componentDidMount() {
this.props.getByUrl(this.props.match.params.url);
}
render() {
const { user: userObject } = this.props;
const { user } = userObject;
if (user) {
return (
<>
<Link to="/">Go back</Link>
<h1>{user.name}</h1>
</>
);
}
return (
<>
<Link to="/">Go back</Link>
<div>Fetching...</div>
</>
);
}
现在,如果用户登陆主页,这效果很好。但是,如果您直接访问链接(即 https://43r1592l0.codesandbox.io/gal-gadot ),则不会,因为用户尚未加载。
我做了一个简单的例子来演示我的问题。 https://codesandbox.io/s/43r1592l0如果你点击一个链接,它就会起作用。如果您直接访问链接 ( https://43r1592l0.codesandbox.io/gal-gadot ),则不会。
我该如何解决这个问题?
最佳答案
我们在reactiflux上的聊天摘要:
回答你的问题:你会如何解决这个问题? -> 高阶组件
您的问题归结为“在加载组件之前重新使用获取所有用户”部分。
假设您想在加载用户后显示一个组件,否则您将显示加载 div:(简单版本)
从“react-redux”导入{connect}
const withUser = connect(
state => ({
users: state.users // <-- change this to get the users from the state
}),
dispatch => ({
loadUsers: () => dispatch({type: 'LOAD_USERS'}) // <-- change this to the proper dispatch
})
)
现在您可以为两个组件重复使用 withUsers
,如下所示:
class Content extends Component {
componentDidMount() {
if (! this.props.users || ! this.props.users.length) {
this.props.loadUsers()
}
}
// ... etc
}
const ContentWithUsers = withUsers(Content) // <-- you will use that class
class Details extends Component {
componentDidMount() {
if (! this.props.users || ! this.props.users.length) {
this.props.loadUsers()
}
}
}
const DetailsWithUsers = withUsers(Details) // <-- same thing applies
我们现在从 connect 创建了一个可重用的 HOC。你可以用 withUsers 包装你的组件,然后你可以重新使用它,但正如你所看到的,你还重写了 componentDidMount() 部分两次
让我们从组件中取出实际的加载(如果我们还没有加载)
部分并将其放入包装器中
const withUsers = WrappedComponent => { // notice the WrappedComponent
class WithUsersHOC extends Component {
componentDidMount () {
if (!this.props.users || !this.props.users.length) {
this.props.loadUsers()
}
}
render () {
if (! this.props.users) { // let's show a simple loading div while we haven't loaded yet
return (<div>Loading...</div>)
}
return (<WrappedComponent {...this.props} />) // We render the actual component here
}
}
// the connect from the "simple version" re-used
return connect(
state => ({
users: state.users
}),
dispatch => ({
loadUsers: () => dispatch({ type: 'LOAD_USERS' })
})
)(WithUsersHOC)
}
现在你可以这样做:
class Content extends Component {
render() {
// ......
}
}
const ContentWithUsers = withUsers(Content)
不再需要实现加载用户,因为 WithUsersHOC
会处理这个问题
您现在可以使用相同的 HOC(高阶组件)包装 Content
和 Details
在加载用户之前,它不会显示实际的组件。 加载用户后,您的组件就会正确呈现。
需要另一个页面来在显示之前加载用户吗?将其也包含在您的 HOC 中
现在,还有一件事可以激发更多的可重用性
如果您不希望 withLoading 组件只能处理用户怎么办?
const withLoading = compareFunction = Component =>
class extends React.Component {
render() {
if (! compareFunction(this.props)) {
return <Component {...this.props} />;
}
else return <div>Loading...</div>;
}
};
现在您可以重复使用它:
const withUsersLoading = withLoading(props => !props.users || ! props.users.length)
const ContentWithUsersAndLoading = withUsers(withUsersLoading(Content)) // sorry for the long name
或者,以更简洁的方式编写:
export default compose(
withUsers,
withLoading(props => !props.users || !props.users.length)
)(Content)
现在您可以在整个应用中重复使用 withUsers
和 withLoading
关于reactjs - React Redux - 如果尚未获得数组,如何加载详细信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53050273/