理解 React 高阶组件

IT技术 javascript reactjs ecmascript-6 higher-order-components
2021-05-12 18:53:37

有人可以解释一下 React 中的高阶组件吗?我已经阅读并重新阅读了文档,但似乎无法更好地理解。根据文档,HOC 通过创建一个返回react组件的主函数,通过将参数传递给该函数来帮助消除重复。我有几个问题。

  • 如果 HOC 创建了一个新的增强组件,是否有可能根本不传入任何组件作为参数?
  • 在诸如this的示例中,它是高阶组件,ButtonEnhancedButton
  • 我尝试创建一个这样的 HOC:

    // createSetup.js
    import React from 'react';
    
    export default function createSetup(options) {
        return class extends React.Component {
            constructor(props) {
                super(props);
    
                this.state = {};
    
                this.testFunction = this.testFunction.bind(this);
            }
    
            testFunction() {
                console.log("This is a test function");
            }
    
            render() {
                return <p>{options.name}</p>
            }
        }
    }
    
    
    // main.js
    import React from 'react';
    import {render} from 'react-dom';
    import createSetup from './createSetup';
    
    render((<div>{() => createSetup({name: 'name'})}</div>),
            document.getElementById('root'););
    

运行它不会显示 HOC,只显示 div

任何人都可以提供比给出的更好的例子吗?

4个回答

HOC 是一种函数,它将组件作为其参数之一,并以某种方式增强该组件。

如果 HOC 创建了一个新的增强组件,是否有可能根本不传入任何组件作为参数?

不,那么它就不是 HOC,因为其中一个条件是它们将一个组件作为参数之一,并返回一个具有一些附加功能的新组件。

在这样的示例中,它是高阶组件,即 Button 或 EnhancedButton。

EnhanceButton是 HOC,FinalButton是增强组件。

我尝试像这样创建一个 HOC:...运行它不会显示 HOC,只显示 div

那是因为你的createSetup函数不是 HOC ......它是一个返回组件的函数,是的,但它不会将组件作为参数来增强它。

让我们看一个基本 HOC 的例子:

const renderWhen = (condition, Component) =>
  props => condition(props)
    ? <Component {...props} />
    : null
);

你可以像这样使用它:

const EnhancedLink = renderWhen(({invisible}) => !invisible, 'a');

现在您EnhancedLink将像一个a组件,但如果您将属性invisible传递true它,它将不会呈现...因此我们增强了a组件的默认行为,您可以使用任何其他组件来执行此操作。

在许多情况下,HOC 函数是柯里化的,组件 arg 放在最后......像这样:

const renderWhen = condition => Component =>
  props => condition(props)
    ? <Component {...props} />
    : null
);

就像connectreact-redux功能……这使得组合更容易。看看recompose

简而言之,如果假设函数类似于组件,那么闭包类似于 HOC。

试试你的 createSetup.js:

const createSetup = options => <p>{options.name}</p>;

和你的 main.js

const comp = createSetup({ name: 'name' });
render((<div>{comp}</div>),
  document.getElementById('root'));

高阶组件 (HOC)是 React 中用于重用组件逻辑的高级技术。具体来说,高阶组件是一个函数,它接受一个组件并返回一个新组件。

HOC 是一个零副作用纯函数

示例:有条件地渲染组件

假设我们有一个只有在用户通过身份验证时才需要呈现的组件——它是一个受保护的组件。我们可以创建一个名为WithAuth()的 HOC来包装该受保护的组件,然后在 HOC 中进行检查,如果用户已通过身份验证,该 HOC 将仅呈现该特定组件。

根据上面的例子,一个基本的withAuth() HOC 可以写成如下:

// withAuth.js
import React from "react";
export function withAuth(Component) {
    return class AuthenticatedComponent extends React.Component {
        isAuthenticated() {
            return this.props.isAuthenticated;
        }

        /**
         * Render
         */
        render() {
            const loginErrorMessage = (
                <div>
                    Please <a href="/login">login</a> in order to view this part of the application.
                </div>
            );

            return (
                <div>
                    { this.isAuthenticated === true ? <Component {...this.props} /> : loginErrorMessage }
                </div>
            );
        }
    };
}

export default withAuth;

上面的代码是一个名为withAuth的 HOC 它基本上接受一个组件并返回一个名为AuthenticatedComponent的新组件,用于检查用户是否已通过身份验证。如果用户未通过身份验证,则返回loginErrorMessage组件;如果用户通过身份验证,则返回包装的组件。

注意:this.props.isAuthenticated 必须从应用程序的逻辑中设置。(或者使用 react-redux 从全局状态中检索它。)

为了在受保护的组件中使用我们的 HOC,我们会像这样使用它:

// MyProtectedComponent.js
import React from "react";
import {withAuth} from "./withAuth.js";

export class MyProectedComponent extends React.Component {
    /**
     * Render
     */
    render() {
        return (
            <div>
                This is only viewable  by authenticated users.
            </div>
        );
    }
}

// Now wrap MyPrivateComponent with the requireAuthentication function 
export default withAuth(MyPrivateComponent);

在这里,我们创建了一个只有经过身份验证的用户才能查看的组件。我们将该组件包装在我们的withAuth HOC 中,以保护该组件免受未经身份验证的用户的攻击。

来源