将 React 组件从函数重构为 ES6 类

Posted

技术标签:

【中文标题】将 React 组件从函数重构为 ES6 类【英文标题】:Refactor a React component from function to ES6 class 【发布时间】:2016-11-10 01:39:38 【问题描述】:

我是 ES6 新手。 对编写 React 组件的不同方式感到有些困惑。 我从“React.createClass”开始,然后移至使用 ES6 类语法“扩展 React.Component”。

按照 Redux 教程,现在我看到他们以这种方式定义组件

import React,  PropTypes  from 'react'

const Todo = ( onClick, completed, text ) => (
    <li onClick=onClick style= textDecoration: completed ? 'line-through' : 'none'  >
        text
    </li>
)

Todo.propTypes = 
    onClick: PropTypes.func.isRequired,
    completed: PropTypes.bool.isRequired,
    text: PropTypes.string.isRequired


export default Todo

我怎样才能重构这个“函数”移动到一个扩展 React.component 的 ES6 类?我猜返回 JSX 是 render() 方法,不是吗? onClick、completed、文本参数呢?

谢谢

【问题讨论】:

【参考方案1】:

对于你的组件,实际上最好将其设为纯函数,而不是 ES6 类,因为它可以作为其props 的函数进行渲染,并且不维护状态。不过,您仍然可以使用 ES6 语法(导出、箭头函数等)。

Facebook's explanation:“在理想情况下,您的大多数组件将是无状态函数,因为将来我们还可以通过避免不必要的检查和内存分配来针对这些组件进行性能优化。这是推荐的模式,如果可能的话。”

import  PropTypes  from 'react'

function Todo = (props) => (
    <li onClick=props.onClick style= textDecoration: props.completed ? 'line-through' : 'none'  >
        props.text
    </li>
)

Todo.propTypes = 
    onClick: PropTypes.func.isRequired,
    completed: PropTypes.bool.isRequired,
    text: PropTypes.string.isRequired


export default Todo

【讨论】:

这正是应该做的。仅仅因为您可以将组件编写为 ES6 类并不意味着所有组件都应该是类。 我支持您的解决方案。我不知道你可以不必为组件中的道具使用 PropTypes.shape。 避免回答问题:“做 X 的最好方法就像 ABC,因此这里是 ABC” - 他想要纯函数版本的 ES6 版本,而不是重复他的确切问题参考。 不应该是const Todo = ...(或function Todo(props) ... )而不是function Todo = ...吗?【参考方案2】:

等效的 ES6 语法是:

import React,  Component, PropTypes  from 'react'

class Todo extends Component 
  render() 
    const  onClick, completed, text  = this.props

    return (
      <li onClick=onClick style= textDecoration: completed ? 'line-through' : 'none'  >
          text
      </li>
    )
  

Todo.propTypes = 
  onClick: PropTypes.func.isRequired,
  completed: PropTypes.bool.isRequired,
  text: PropTypes.string.isRequired


export default Todo

如果您使用babel 转译您的代码并且您拥有class properties transform,那么您可以执行以下操作:

import React,  Component, PropTypes  from 'react'

class Todo extends Component 
  static propTypes = 
    onClick: PropTypes.func.isRequired,
    completed: PropTypes.bool.isRequired,
    text: PropTypes.string.isRequired
  

  render() 
    const  onClick, completed, text  = this.props

    return (
      <li onClick=onClick style= textDecoration: completed ? 'line-through' : 'none'  >
          text
      </li>
    )
  


export default Todo

为了清楚起见,第二个示例不能被视为“标准 ES6”,但是我发现静态属性非常干净,所以我认为也值得展示这种方法。

【讨论】:

OP 要求一个 ES6 类,你的回答是语法错误。【参考方案3】:

从 ES6 迁移到 TypeScript,对于 React 17 及更高版本,您可以这样做:

import type  FC  from "react";

interface TodoProps 
  onClick: () => void;
  hasCompleted: () => boolean;
  text: string;


const Todo: FC<TodoProps> = ( onClick, hasCompleted, text ) => (
  <li
    onClick=onClick
    style= textDecoration: hasCompleted ? "line-through" : "none" 
  >
    text
  </li>
);

export default Todo;

如果您不想要 implicit 孩子,您可以删除 import type 行并重写如下:

const Todo = ( onClick, hasCompleted, text : TodoProps) => (

但是,如果您这样做了,您还需要将children 添加到类型声明中,并花时间尝试找出应该如何输入它——如果假设使用FC,则不需要使用children

有关在 TypeScript 中声明函数的更多信息,请访问 TypeScript 文档中的More on Functions。

【讨论】:

以上是关于将 React 组件从函数重构为 ES6 类的主要内容,如果未能解决你的问题,请参考以下文章

React使用ES6语法重构组件代码

react中从类重构为功能钩子组件

如何编写扩展功能组件的 ES6 类 React 组件?

React组件——类组件

将函数绑定到组件 React es6 的不同方法是啥 [重复]

如何将 React 类组件转换为函数组件