访问 React 元素的 children
Access children of react element
想象一下有 React 组件
function List() {
return (<ul>
<li>1</li>
<li>2</li>
</ul>
);
}
我想创建 high-order 组件来修改,例如,所有 li
节点的样式。
function makeRed(component) {
return function(props) {
const element = React.createElement(component, props);
return React.cloneElement(
element,
element.props,
React.Children.map(
element.props.children,
ch => React.cloneElement(ch, {
...ch.props,
style: {
backgroundColor: "red"
}
},
ch.props.children
)
)
);
}
}
但是。这是行不通的。 Children 为空。
有趣的是,如果我直接创建组件,这会起作用,比如
...
const element = <ul><li>1</li><li>2</li></ul>;
...
问题:如何访问任何 React 元素的 children 和 grandchildren?
正如@hamms 指出的那样,这是一种反模式。有 better ways to implement themes in React 使用普通的旧 CSS。
也就是说,这是对您的用例的一个有效示例的 hack - https://codesandbox.io/s/ymqwyww22z。
基本上,这是我所做的:
使 List
成为基于 class 的组件。把一个功能组件包装成一个也不嫌麻烦
import React, { Component } from "react";
export default class List extends Component {
render() {
return (
<ul>
<li>1</li>
<li>2</li>
</ul>
);
}
}
在动态 class Red<Component>
中实现 render
以首先获取从基本组件的渲染返回的元素树,然后对其进行编辑。
import React from "react";
export default function makeRed(Component) {
return class RedComponent extends Component {
constructor(props) {
super(props);
RedComponent.displayName = `Red${Component.name}`;
}
render() {
let componentElement = super.render();
let { children, ...rest } = componentElement.props;
children = React.Children.map(children, child => {
return React.cloneElement(child, {
...child.props,
style: {
backgroundColor: "red"
}
});
});
return React.cloneElement(componentElement, rest, ...children);
}
};
}
这与 makeRed
的 createElement
版本有何不同?
作为 makeRed
returns 一个 HOC,当你在你的 App
组件中使用它时,你不会为它分配道具。像这样...
function App() {
return <RedList />; // no props!
}
因此在动态组件函数中,您使用 createElement
创建新实例的地方,component.props
不携带任何子项。由于 List
创建了自己的子项,因此您需要获取并修改它们,而不是从 props
.
中读取子项
想象一下有 React 组件
function List() {
return (<ul>
<li>1</li>
<li>2</li>
</ul>
);
}
我想创建 high-order 组件来修改,例如,所有 li
节点的样式。
function makeRed(component) {
return function(props) {
const element = React.createElement(component, props);
return React.cloneElement(
element,
element.props,
React.Children.map(
element.props.children,
ch => React.cloneElement(ch, {
...ch.props,
style: {
backgroundColor: "red"
}
},
ch.props.children
)
)
);
}
}
但是。这是行不通的。 Children 为空。
有趣的是,如果我直接创建组件,这会起作用,比如
...
const element = <ul><li>1</li><li>2</li></ul>;
...
问题:如何访问任何 React 元素的 children 和 grandchildren?
正如@hamms 指出的那样,这是一种反模式。有 better ways to implement themes in React 使用普通的旧 CSS。
也就是说,这是对您的用例的一个有效示例的 hack - https://codesandbox.io/s/ymqwyww22z。
基本上,这是我所做的:
使
List
成为基于 class 的组件。把一个功能组件包装成一个也不嫌麻烦import React, { Component } from "react"; export default class List extends Component { render() { return ( <ul> <li>1</li> <li>2</li> </ul> ); } }
在动态 class
Red<Component>
中实现render
以首先获取从基本组件的渲染返回的元素树,然后对其进行编辑。import React from "react"; export default function makeRed(Component) { return class RedComponent extends Component { constructor(props) { super(props); RedComponent.displayName = `Red${Component.name}`; } render() { let componentElement = super.render(); let { children, ...rest } = componentElement.props; children = React.Children.map(children, child => { return React.cloneElement(child, { ...child.props, style: { backgroundColor: "red" } }); }); return React.cloneElement(componentElement, rest, ...children); } }; }
这与 makeRed
的 createElement
版本有何不同?
作为 makeRed
returns 一个 HOC,当你在你的 App
组件中使用它时,你不会为它分配道具。像这样...
function App() {
return <RedList />; // no props!
}
因此在动态组件函数中,您使用 createElement
创建新实例的地方,component.props
不携带任何子项。由于 List
创建了自己的子项,因此您需要获取并修改它们,而不是从 props
.