1

想象一下,我有一些“页面”组件,它需要从服务器请求数据。它请求的数据将取决于当前用户是否被认证。此外,如果登录,页面将要重新加载数据。我的问题是,我如何使用HOC而不是继承来完成像这样的事情?React Higher Order组件条件数据加载

为了说明这个问题,我将演示一个使用继承的解决方案。该计划将有以下对象。我会留下样板代码。

  • session:一个EventEmitter发射start当会话改变(无论是一个登录或注销)。
  • Page:在所有页面从
  • MyPage继承父:的Page在这个例子中,子类
  • 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()中的更改。

+0

可能重复[反应:如何用HOC打包组件? (跨组件访问登录属性)](https://stackoverflow.com/questions/42372614/react-how-to-wrap-component-with-hoc-access-login-property-across-components) –

+0

@NathanP。这是一个类似的问题,但我认为有一些重要的区别。 1)我没有使用REDX,这只是原始的反应。 2)我没有试图通过登录标志或用户名进行渲染,我试图在会话状态发生变化时执行一些特定于组件的操作。 – CaptainStiggz

回答

1

使用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); 

希望这有助于! :)