Skip to content

React cloneElement 和 createElement

createElement

用来创建一个组件,它其实是一个 jsx 的语法糖。它生成的 ts 的类型为 React.createElement

js
const element = createElement(type, props, ...children);
jsx
function App() {
  const el = (
    <h1 className="greeting" style={{ color: "red" }}>
      Hello
    </h1>
  );
  return el;
}

等价于:

jsx
function App() {
  const el = React.createElement("h1", { className: "greeting", style: { color: "red" } }, "Hello");
  return el;
}

它的第 1 个参数还可以是一个组件的名字,第 2 个参数传递给组件的属性, 后面的参数为 children。

tsx
interface Props {
  color: string;
  children?: React.ReactNode;
}

const Greeting: FC<Props> = (props) => {
  const { color, children } = props;
  return <div style={{ color }}>Greeting {children}</div>;
};

function App() {
  return createElement(Greeting, { color: "red" }, <p>David</p>, <p>Zheng</p>);
}

// 或者
function App() {
  return createElement(Greeting, {
    color: "red",
    children: [<p>David</p>, <p>Zheng</p>]
  });
}

等价于:

jsx
<div style="color: red;">
  Greeting <p>David</p>
  <p>Zheng</p>
</div>

cloneElement

用来 clone 一个组件, 并且覆盖组件的 props。

js
const clonedElement = cloneElement(element, props, ...children);

例子:

jsx
import { cloneElement } from "react";

// ...
const clonedElement = cloneElement(
  <Row title="Cabbage">Hello</Row>,
  { isHighlighted: true },
  "Goodbye"
);

console.log(clonedElement); // <Row title="Cabbage" isHighlighted={true}>Goodbye</Row>

另外一个具体的例子如下:

tsx
interface Props {
  title: string;
  children?: React.ReactNode;
  style?: React.CSSProperties;
}

const Greeting: FC<Props> = ({ title, style, children }) => {
  return (
    <h1 title={title} style={style}>
      {children}
    </h1>
  );
};

function App() {
  return cloneElement(
    <Greeting title="David">Hello</Greeting>,
    { title: "Mike", style: { color: "red" } },
    "Goodbye"
  );
}
// 相当于   <Greeting title="Mike" style="color: red">Goodbye</Greeting>,

cloneElement 和 createElement 区别

区别是:一个是创建 element,一个是克隆 element 并且改变 props