在 React 中定义和导出 HOC

Posted

技术标签:

【中文标题】在 React 中定义和导出 HOC【英文标题】:Defining and exporting HOC in React 【发布时间】:2018-05-11 16:40:56 【问题描述】:

我一直在研究 React 中的高阶组件。我的要求是我需要扩展一组组件,以便在不重写整个组件的情况下为它们提供更多功能。在这种情况下,我在 react 中发现了 HOC 概念,可以使用纯函数扩展组件。我的问题是,我可以将扩展组件导出为普通组件吗?举个例子

需要扩展的组件

class foo extends React.Component 
    render()
        //something
    


export default foo;

HOC 组件

function bar(foo) 
    render() 
         return <foo ...this.props ...this.state />;
    


export default bar;

我可以这样使用组件吗?还是我做错了?

【问题讨论】:

【参考方案1】:

HOC 会接受一个组件,添加更多功能并返回一个新组件,而不仅仅是返回组件实例,

你会做的是

function bar(Foo) 

   return class NewComponent extend React.Component 
        //some added functionalities here
        render() 
            return <Foo ...this.props ...otherAttributes />
        
   



export default bar;

现在,当您想向组件添加一些功能时,您可以创建组件的实例,例如

const NewFoo = bar(Foo);

你现在可以像这样使用

return (
    <NewFoo ...somePropsHere />
)

此外,您可以允许 HOC 采用默认组件并将其导出为默认组件并在其他地方使用它,例如

function bar(Foo = MyComponent) 

然后创建一个类似的导出

const wrapMyComponent = Foo();
export  wrapMyComponent as MyComponent ;

HOC 的典型用例可能是 HandleClickOutside 功能,您可以传递一个需要基于 handleClickOutside 功能采取行动的组件

【讨论】:

很好的答案。一个问题。是否可以编写无需创建实例即可直接渲染的 HOC 组件。 @ImeshChandrasiri 在这种情况下,它不是 HOC,而是呈现另一个组件的组件,但是您可以默认导出一些用 HOC 包装的组件,即 HOC 并始终采用默认组件并返回它 不应该是const wrapMyComponent = Foo();const wrapMyComponent = bar(); 吗?【参考方案2】:

另一种方式可能是这样的:

制作一个 Foo 组件

class Foo extends React.Component 
    render() 
      return ( < h1 > hello I am in Foo < /h1>)
      
    

制作一个 HOC 组件。

class Main extends React.Component 
  constructor(props) 
    super(props);
  
  render() 
    const 
      component, props
     = this.props;
    //extract the dynamic component passed via props.
    var Component = component;

    return ( < div > 
          < h1 > I am in main < /h1> 
          < Component ...props > < /Component>
          </div > );
  



ReactDOM.render( < Main component = 
    Foo
   > < /Main>,
  document.getElementById('example')
);

工作代码here

【讨论】:

【参考方案3】:

是的,你可以

const bar = (Foo) => 
   return class MyComponent extend Component 
        render() 
            return <Foo ...this.props />
        
   

//我们的Foo组件代码在这里

export default bar(Foo)

但这又取决于功能。例如:假设您正在使用反应路由器,并且想要在渲染组件之前检查用户是否存在,但未通过 HOC。例如:

<Route path="/baz" component=auth(Foo) />

改为使用新组件。

注意:NewComponent 连接到 redux,用户(状态)作为 props 传递

class NewRoute extends Component
    render()
        const component:Component, ...otherProps = this.props;

        return(
          <Route render=props => (
            this.props.user? (
              <Component ...otherProps /> 
              ):(
              <Redirect  to="/" />
                )
            ) 
          />
        );
    

然后在路线上

<NewRoute path='/foo' component=Foo />

【讨论】:

以上是关于在 React 中定义和导出 HOC的主要内容,如果未能解决你的问题,请参考以下文章

使用多个 HOC 包装器导出 React 组件?

在 react 里写 vue3 ? 还写了自定义 hooks和 Hoc 构建了响应式 !

如何为 Apollo 的 React HOC 定义 props 接口?

在 HoC 中使用反应钩子时的警告

[react] 使用ES6的class定义的组件不支持mixins了,那用什么可以替代呢?

React HOC(高阶组件)