【问题标题】:converting react classes to functions with redux使用 redux 将反应类转换为函数
【发布时间】:2018-03-26 04:11:20
【问题描述】:

在获得类似功能之后,我还是 react/redux 的新手

用户.js

class User extends React.Component {
    componentWillMount() {
        this.props.fetchUser(.....);
}

render() {
    return (
        <Profile />
    )
}

export default connect(null, {fetchUser})(User);

Profile.js

class Profile extends React.Component {
    render() {

        const { user } = this.props

        return (    
                <h1>{user.profile.name}</h1>
        )
}

const mapStateToProps = state => ({
    user: state.store.user
});

export default connect(mapStateToProps, {})(Profile)

actions.js

export const fetchUser = (.....) => dispatch => {
    fetch()
    .....
}

reducers.js

case FETCH_USER:
    return {
        ...state,
        user: action.payload.user
    };    

据我了解,用户组件从 componentWillMount() 上的 connect 调用一个操作 (fetchUser)。该操作调用 api,获取数据,reducer 将其添加到状态内的存储中。 Profile 组件然后可以使用 connect 将来自 fetchUser 的数据映射到 store 中并显示该数据。

看了一些教程,包括https://github.com/reactjs/redux/blob/master/docs/basics/UsageWithReact.md

看起来事情可以在不使用类的情况下稍微简化。

如果我要将 User 和 Profile 组件更改为更实用的方式,我会怎么做?

例如。

const User = () => {
    return (
        <Profile />
    )
}

如何调度 fetchUser 操作以及如何模拟它以使用 componentWillMount() 的流程调用?

还是我把事情复杂化了?

【问题讨论】:

    标签: reactjs react-redux


    【解决方案1】:

    还有一种方法可以在功能组件中支持生命周期方法。 https://www.npmjs.com/package/react-pure-lifecycle

    import React from 'react';
    import lifecycle from 'react-pure-lifecycle';
    
     // create your lifecycle methods
    const componentDidMount = (props) => {
       console.log('I mounted! Here are my props: ', props);
    };
    
    // make them properties on a standard object
    const methods = {
      componentDidMount
    };
    
    const FunctionalComponent = ({children}) => {
    return (
      <div>
        {children}
      </div>
     );
    };
    
    // decorate the component
    export default lifecycle(methods)(FunctionalComponent);
    

    【讨论】:

    • 它使用基于类的组件github.com/planttheidea/react-pure-lifecycle/blob/master/src/…而不是功能组件创建基于类的HOC
    • 从用户的角度来看,这个库提供了一个 HOC 来将生命周期方法插入到他们已经编写的功能组件中。在我看来,写一堂课也是最干净的。
    • 根据库使用这个的好处是Not a whole lot of gain here other than the fact that you now have a pure function that you can test independently (no need to create an instance). This decoration method will also work on PureComponents
    • 我们可以用可重复使用的 HOC 做同样的事情
    【解决方案2】:

    我认为你应该继续在 redux 中使用 statefull 组件... https://medium.com/@antonkorzunov/2-things-about-purecomponent-you-probable-should-know-b04844a90d4

    Redux connect — 是一个 PureComponent。 是的 —— 非常重要的一点,一个分子的 HoC 是一个纯粹的。甚至可以在其他纯组件中工作。并从当前上下文中获取存储。

    同样适用,例如,styled-component — 您可以用 PureComponent 包装它,但它仍会响应主题更改。

    解决方案很简单 — 绕过逻辑,使用老式事件总线、订阅、等待和发出事件。

    样式化组件:

    componentWillMount() {      
    // subscribe to the event emitter. This      
    // is necessary due to pure components blocking 
    // context updates, this circumvents      
    // that by updating when an event is emitted.
    
       const subscribe = this.context[CHANNEL];
       this.unsubscribe = subscribe(nextTheme => {  <----- MAGIC
    React-redux:
    
    trySubscribe() {
     if (shouldSubscribe && !this.unsubscribe) {
      this.unsubscribe = 
         this.store.subscribe(this.handleChange);  <----- MAGIC
     }
    }
    componentDidMount() {
      this.trySubscribe();
    }
    

    因此,即使父级纯组件会阻止任何更新,您也可以捕获更改、存储更新、上下文变量更改或其他所有内容。

    所以 — 纯组件内部的东西非常脏,绝对不纯。它是由副作用驱动的! 但是这个绕过了直接的逻辑流程,并且与其他应用程序的工作方式不同。

    所以 — 小心点。别忘了魔法。

    啊和……。 这就是为什么任何 redux store 更新都会导致每个连接的组件重绘,以及为什么你应该使用 reselect just next 来连接 HoC —

    停止不必要的更改传播。 但你应该从另一个角度阅读:

    redux-connect 是变更传播的来源。 redux connect 是变更传播的结束。它仍然是 PureComponent。 这导致了一件非常方便的事情 — 您只能使用 redux-connect 来控制更改传播。只需为改变创造一个界限。让我们在另一篇文章中讨论这个问题。

    结论 纯组件使您的应用程序保持快速。有时 — 更可预测,但通常 — 不可预测,只要它们改变了应用程序的工作方式。

    无状态组件不是纯粹的,并且可能比任何类型的 PureComponents 运行得慢。

    但是……如果您非常希望创建一个具有良好用户体验的快速应用程序 — 您必须使用纯组件。

    别无选择。但是,现在 —— 你知道了隐藏的真相,还知道了一些魔法……

    【讨论】:

      【解决方案3】:
      1. React 建议在componentDidMount() 中发出ajax 请求,而不是在componentWillMount() 中。有关这方面的更多信息,请阅读this post

      2. 既然要在componentDidMount() 中发出ajax 请求,就需要一个类。编写组件定义有两种方式:功能组件和类组件。函数式组件更简洁,但是你没有像componentDidMount() 这样的组件生命周期方法。可以把它想象成一个将 props 作为输入和输出 DOMs(在 JSX 中)的渲染函数。要覆盖这些生命周期方法,您需要将它们定义为一个类。

      3. 1234563 dispatch(fetchUser(..))componentDidMount()connect(..)ed 组件获得由Redux store 传递给它的dispatch(..) 函数。

      如果你想了解它在其他 redux 应用中是如何实现的,请查看 redux.js repo 中的官方示例应用,关注actionscontainershttps://github.com/reactjs/redux/tree/master/examples

      【讨论】:

        【解决方案4】:

        在您的情况下,您可以继续使用 statefull components 没有错 ,如果你需要用功能方式

        周围有工作

        https://github.com/mobxjs/mobx/issues/162

        建议

        在 componentDidMount 中调用 api 比调用更有意义 componentWillMount ,因为你可以向用户展示一些东西是 正在获取。

        【讨论】:

          【解决方案5】:

          我认为,User 组件设计得很好。它将充当Profile 提供数据的容器。

          不要让Profile面向组件类,而应该是Stateless

          User 组件传递Profile 组件所需的数据。 您不需要使用redux-connect 连接Profile 组件。只需将其渲染为Child component of User

          个人资料

          const Profile = (props) => {
          
            const {user, likeProfile} = props;
            //likeProfile()//call like this using dom event or programmatically.
            return (
              <h1>{user.profile.name}</h1>
            )
          }
          

          您需要对User 组件进行一些更改。 通过mapStateToProps 获取Profile 组件的状态。

          class User extends React.Component {
            componentWillMount() {
                this.props.fetchUser(.....);
          }
          
          render() {
          
            const {user, likeProfile} = this.props;
            return (
                <Profile user= {user} likeProfile={likeProfile} /> //passed the user data to Profile component vua User
            )
          }
          

          User 连接中映射Profile 的用户状态。

          const mapStateToProps = (state)=>{
            return{
              user : state.somereducerkey.user //this will be accessible in Profile via props { user}
            } 
          }
          export default connect(mapStateToProps, {fetchUser, likeProfile})(User);
          

          【讨论】:

          • 我想知道这个,假设我的 Profile 组件有一个类似 likeProfile() 的操作,我如何将该操作从 User 组件传递到 Profile 组件?
          • @totalnoob 我已经更新了答案 assming likeProfile 电话。
          猜你喜欢
          • 2020-02-14
          • 1970-01-01
          • 2018-12-16
          • 1970-01-01
          • 1970-01-01
          • 2020-08-06
          • 1970-01-01
          • 1970-01-01
          • 2021-01-16
          相关资源
          最近更新 更多