首页 > 解决方案 > 这是 React 中高阶组件(HOC)的有效实现吗?

问题描述

我昨天问了这个问题:跨组件的React共享方法

import React from 'react';

class LoginForm extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            email: '',
            password: '',
        };

        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(e) {
        const target = e.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;

        this.setState({
            [name]: value
        });
    }

由于我在handleChange(e)整个应用程序中多次重用,我决定将其分离成一个高阶组件,如下所示:

import React from 'react';

const withHandleChange = (WrappedComponent) => {
    return class extends React.Component {
        constructor(props) {
            super(props);

            this.state = {
            };
        }

        handleChange = e => {
            const target = e.target;
            const value = target.type === 'checkbox' ? target.checked : target.value;
            const name = target.name;

            this.setState({
                [name]: value
            });
        }

        render() {
            return (
                <WrappedComponent
                    handleChange={this.handleChange}
                    form={this.state}
                    {...this.props}
                />
            );
        }
    }
};

export default withHandleChange;

我现在没有维护输入字段的状态,而是让LoginFormHOC 完成了这项工作,并将此状态作为名为form. handleChange我还将该方法作为道具传递下来。

在原始LoginForm组件中,我呈现以下内容:

<input type="text" placeholder="Email" name="email" value={this.props.form.email} onChange={this.props.handleChange} />

我这样包装LoginForm

const WrappedLoginForm = withHandleChange(LoginForm);

const LoginBox = props => (
    <div className="login-box">
        <WrappedLoginForm />
    </div>
);

这是一个有效的实现吗?我主要关心的两个问题是(1)将状态作为道具传递给WrappedComponent定义withHandleChange,以及(2)渲染WrappedLoginForm,因为我读过你不应该在渲染方法中使用 HOC。

至于(1),这有效吗?有没有更好的方法来完成我正在做的事情?

至于(2),我认为他们的意思是我不应该在 render 方法中运行 HOC函数,而只是使用包装的组件(就像我现在所做的那样)应该没问题。但是,我有点困惑,希望得到一些确认。

任何和所有建议都会有所帮助。谢谢!

标签: javascriptreactjshigher-order-functionsreact-component

解决方案


由于下面的表达式,不允许在渲染生命周期中使用 HOC

const WrappedLoginForm = withHandleChange(LoginForm);

确实声明了一个组件。而且您知道渲染生命周期可能会执行多次,这取决于您的应用程序到底发生了什么。然后结果是不止一次执行包装组件的声明,这可能导致意外行为。我认为这是它被禁止的根本原因。

为了避免这种错误,非常推荐在内部组件被导出(或导入)的地方声明被包裹的组件。喜欢:LoginForm.js

export default withHandleChange(LoginForm)

或者

import LoginForm from 'somewhere'

const WrappedLoginForm = withHandleChange(LoginForm);

推荐阅读