javascript - 这是 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;
我现在没有维护输入字段的状态,而是让LoginForm
HOC 完成了这项工作,并将此状态作为名为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函数,而只是使用包装的组件(就像我现在所做的那样)应该没问题。但是,我有点困惑,希望得到一些确认。
任何和所有建议都会有所帮助。谢谢!
解决方案
由于下面的表达式,不允许在渲染生命周期中使用 HOC
const WrappedLoginForm = withHandleChange(LoginForm);
确实声明了一个组件。而且您知道渲染生命周期可能会执行多次,这取决于您的应用程序到底发生了什么。然后结果是不止一次执行包装组件的声明,这可能导致意外行为。我认为这是它被禁止的根本原因。
为了避免这种错误,非常推荐在内部组件被导出(或导入)的地方声明被包裹的组件。喜欢:LoginForm.js
export default withHandleChange(LoginForm)
或者
import LoginForm from 'somewhere'
const WrappedLoginForm = withHandleChange(LoginForm);
推荐阅读
- html - html header navbar 和 main 的位置
- sql-server - 无法在 SQL Server 中显示计数
- python - 将列中的值汇总到多年 Jahre 的定义值
- google-sheets - 删除时间、符号/标点符号、将日期标准化为 d/m/yyyy 并从结果中删除重复项的公式
- php - 此字符串日期“10/05/2025”未转换为 dateformat php
- ruby-on-rails - Rails STI 子类在查询父类时被加载
- hazelcast - 启动 hazelcast 管理控制台时上下文初始化期间遇到异常
- node.js - create-react-app 不生成 package.lock 文件
- javascript - 使用类名从数组中删除
- python - 键入一个可调用的函数