React 高阶组件条件数据加载
React Higher Order Component conditional data load
假设我有一些 "page" 组件,它需要从服务器请求数据。它请求的数据将取决于当前用户是否经过身份验证。此外,在登录的情况下,页面将需要重新加载数据。我的问题是,如何使用 HOC 而不是继承来完成这样的事情?
为了说明问题,我将演示一个使用继承的解决方案。该程序将具有以下对象。我将省略样板代码。
session
:当会话更改(登录或注销)时发出 start
的 EventEmitter
。
Page
: 所有页面继承自 的superclass
MyPage
:本例中Page
的subclass
API
: 将是一个 API class 用于从服务器检索数据
代码如下:
// 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 的解决方案,但似乎没有继承那么优雅。它仍然要求每个 "subclass" 页面都有一个方法 loadData
,并且需要在每个 "subclass's" 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
这种模式会经常发生:我想加载一些数据,然后在会话更改时重新加载。我想了解 "react" 实现相同目标的方法。
编辑:我没有尝试通过 HOC 传递用户名或 "loggedIn" 标志。也就是说 <WrappedComponent isLoggedIn={session.isAuthenticated()} {...props} />
之类的东西不会在这里删掉。将 API 逻辑绑定到 props
要求我检查 MyPage.componentWillUpdate()
.
中的更改
使用 HOC 时,不应将 loadData
函数放在包装组件上。而是将函数作为参数传递给 HOC 构造函数。
类似的内容可能对您有用。 sessionHoc
函数采用回调函数,每次会话状态更改时都会调用该回调函数。它的结果将作为 data
属性传递给 WrappedComponent
。
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);
希望这对您有所帮助! :)
假设我有一些 "page" 组件,它需要从服务器请求数据。它请求的数据将取决于当前用户是否经过身份验证。此外,在登录的情况下,页面将需要重新加载数据。我的问题是,如何使用 HOC 而不是继承来完成这样的事情?
为了说明问题,我将演示一个使用继承的解决方案。该程序将具有以下对象。我将省略样板代码。
session
:当会话更改(登录或注销)时发出start
的EventEmitter
。Page
: 所有页面继承自 的superclass
MyPage
:本例中Page
的subclassAPI
: 将是一个 API class 用于从服务器检索数据
代码如下:
// 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 的解决方案,但似乎没有继承那么优雅。它仍然要求每个 "subclass" 页面都有一个方法 loadData
,并且需要在每个 "subclass's" 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
这种模式会经常发生:我想加载一些数据,然后在会话更改时重新加载。我想了解 "react" 实现相同目标的方法。
编辑:我没有尝试通过 HOC 传递用户名或 "loggedIn" 标志。也就是说 <WrappedComponent isLoggedIn={session.isAuthenticated()} {...props} />
之类的东西不会在这里删掉。将 API 逻辑绑定到 props
要求我检查 MyPage.componentWillUpdate()
.
使用 HOC 时,不应将 loadData
函数放在包装组件上。而是将函数作为参数传递给 HOC 构造函数。
类似的内容可能对您有用。 sessionHoc
函数采用回调函数,每次会话状态更改时都会调用该回调函数。它的结果将作为 data
属性传递给 WrappedComponent
。
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);
希望这对您有所帮助! :)