简体   繁体   English

这是 React 中高阶组件 (HOC) 的有效实现吗?

[英]Is this an efficient implementation of a higher-order component (HOC) in React?

I asked this question yesterday: React sharing method across components昨天问了这个问题: 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
        });
    }

Since I'm reusing handleChange(e) many times throughout my application, I decided to separate it out into a higher-order component as so:由于我在整个应用程序中多次重用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;

Instead of making LoginForm maintain the state of the input fields, I now have the HOC accomplish that, and I pass this state down as a prop called form .我现在没有让LoginForm维护输入字段的状态,而是让 HOC 完成它,并将此状态作为名为form的道具传递下来。 I also pass down the handleChange method as a prop.我还将handleChange方法作为道具传递。

And in the original LoginForm component, I render the following:在原始LoginForm组件中,我呈现以下内容:

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

I wrapped LoginForm as so:我这样包装LoginForm

const WrappedLoginForm = withHandleChange(LoginForm);

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

Is this a valid implementation?这是一个有效的实现吗? My main two concerns are (1) passing down the state as a prop to WrappedComponent in the withHandleChange definition, and (2) rendering WrappedLoginForm since I've read you shouldn't use HOCs inside the render method.我主要关注的两个问题是 (1) 在withHandleChange定义中将状态作为道具传递给WrappedComponent ,以及 (2) 呈现WrappedLoginForm因为我已经读过你不应该在呈现方法中使用WrappedLoginForm

As for (1), is this efficient?至于(1),这是有效的吗? Is there a better way to accomplish what I'm doing?有没有更好的方法来完成我正在做的事情?

As for (2), I think they meant that I shouldn't run the HOC function inside the render method, but simply using a wrapped component (as I do now) should be fine.至于 (2),我认为他们的意思是我不应该在 render 方法中运行 HOC函数,而只是使用包装的组件(就像我现在所做的那样)应该没问题。 However, I'm slightly confused and would appreciate some confirmation.但是,我有点困惑,希望得到一些确认。

Any and all suggestions would be helpful.任何和所有建议都会有所帮助。 Thanks!谢谢!

It's disallowed to use HOCs in the render lifecycle because of that below expression由于以下表达式,不允许在渲染生命周期中使用 HOC

const WrappedLoginForm = withHandleChange(LoginForm);

does declare a component.确实声明了一个组件。 And you know render lifecycle might be executed more than one time depends on what exactly happens to your app.而且您知道渲染生命周期可能会执行多次,这取决于您的应用程序究竟发生了什么。 Then It results to be more than one time that declaration of the wrapped component will be executed which may lead to unexpected behavior.那么结果是被包装组件的声明将被执行不止一次,这可能导致意外行为。 I think this is the root reason why it's disallowed.我认为这是它被禁止的根本原因。

To avoid this kind of mistake, it is very recommended to declare the wrapped component at the place the inner component is exported(or imported).为了避免这种错误,非常建议在内部组件导出(或导入)的地方声明被包裹的组件。 Like: LoginForm.js喜欢:LoginForm.js

export default withHandleChange(LoginForm)

or或者

import LoginForm from 'somewhere'

const WrappedLoginForm = withHandleChange(LoginForm);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM