reactjs - React Redux - 如果尚未获得数组,如何加载详细信息?

标签 reactjs redux

我有一个带有 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(高阶组件)包装 ContentDetails

在加载用户之前,它不会显示实际的组件。 加载用户后,您的组件就会正确呈现。

需要另一个页面来在显示之前加载用户吗?将其也包含在您的 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)

现在您可以在整个应用中重复使用 withUserswithLoading

关于reactjs - React Redux - 如果尚未获得数组,如何加载详细信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53050273/

相关文章:

reactjs - 如何防止Redux多次显示同一错误?

javascript - 在 React 中使用 window.location.reload 是否正确?

reactjs - 使用react-loadable加载页面的错误方法

javascript - 如何将 "await"用于生成器函数是 ES6?

asp.net-mvc - 从组件到通过服务器端渲染存储的初始状态

javascript - React 中的加载器

reactjs - React.js/Redux : setInterval and clearInterval in Reducers

javascript - import 在测试时返回 undefined 而不是 react 组件

reactjs - 用户信息存放在redux store还是本地存储中?

javascript - 如何使 @connect 装饰器与 redux-saga 一起工作?