1

想象一下,我有一些“页面”组件,它需要从服务器请求数据。它请求的数据将取决于当前用户是否经过身份验证。此外,在登录的情况下,页面将需要重新加载数据。我的问题是,我怎样才能使用 HOC 而不是继承来完成这样的事情?

为了说明这个问题,我将演示一个使用继承的解决方案。该程序将具有以下对象。我将省略样板代码。

  • session:当会话更改(登录或注销)时发出的EventEmitterstart
  • Page:所有页面继承自的超类
  • MyPagePage本例中的子类
  • API: 将是一个用于从服务器检索数据的 API 类

这是代码:

// Page superclass
class Page extends React.Component {

   componentWillMount() {
      session.on("start", this.loadData);
      this.loadData();
   }

   loadData() {
      // this method is overwritten in subclasses
   }
}

// MyPage subclass
class MyPage extends Page {

   loadData() {
      if(session.isAuthenticated()) {
         API.loadPrivateData();
      } else {
         API.loadPublicData();
      }
   }
}

这是一个使用 HOC 的解决方案,但似乎不如继承优雅。它仍然要求每个“子类”页面都有一个方法loadData,并且要求在每个“子类”中调用该方法componentWillMount

// Page HOC
function Page(WrappedComponent) {
   return class EnhancedPage extends React.Component {

      componentWillMount() {
         session.on("start", this.loadData);
         // this._page.loadData() will fail here
         // since this._page is undefined until rendering finishes
      }

      loadData() {
         this._page.loadData();
      }

      render() {
         return <WrappedComponent {...props} ref={(e) => { this._page = e; }} />
      }
   }
}

// MyPage
class MyPage extends React.Component {

   componentWillMount() {
      this.loadData();
   }

   loadData() {
      if(session.isAuthenticated()) {
         API.loadPrivateData();
      } else {
         API.loadPublicData();
      }
   }
}

const component = Page(MyPage)

// what would make sense here is to have a method something like
// const component = Page(MyPage, () => MyPage.loadData())
// but then the MyPage.loadData logic would need to be defined
// elsewhere

这种模式经常发生:我想加载一些数据,然后在会话更改时重新加载。我想了解完成相同操作的“反应”方式。

编辑:我不想通过 HOC 传递用户名或“loggedIn”标志。也就是说<WrappedComponent isLoggedIn={session.isAuthenticated()} {...props} />,这里不会削减它。将 API 逻辑绑定到props要求我检查MyPage.componentWillUpdate().

4

1 回答 1

1

使用 HOC 时,不应将loadData函数放在包装的组件上。而是将函数作为参数传递给 HOC 构造函数。

像这样的东西可能对你有用。该sessionHoc函数采用一个回调函数,每次会话状态更改时都会调用该回调函数。它的结果将WrappedComponent作为data道具传递给。

function sessionHoc(onSessionChange) {
    return function (WrappedComponent) {
        return class extends React.Component {
            constructor(props) {
                super(props);

                this.state = {
                    data: null,
                };

                session.on('start', this.handleSessionChange.bind(this));
            }

            handleSessionChange() {
                this.setState({
                    data: onSessionChange(),
                });
            }

            render() {
                return <WrappedComponent data={data} {...this.props} />
            }
        };
    };
}

class MyPage extends React.Component {
    render() {
        // Just access this.props.data here!
    }
}

const EnhancedPage = sessionHoc(function () {
    if (session.isAuthenticated()) {
        return API.loadPrivateData();
    } else {
        return API.loadPublicData();
    }
})(MyPage);

希望这有帮助!:)

于 2017-09-01T08:23:09.953 回答