我正在尝试映射片段的子级,而该片段又是组件的子级。例如:
const Frag = () => (
<React.Fragment key="test-key">
<div>test1</div>
<div>test2</div>
</React.Fragment>
);
const Outer = ({ children }) => (
<div>
{
React.Children.map(children, (child) => (
<a>
{child}
</a>
))
}
</div>
);
// Usage
<Outer>
<Frag />
</Outer>
这将导致单个
a
标签,即使片段内部有多个 div。文档(https://reactjs.org/docs/react-api.html#reactchildrenmap)似乎表明这应该与键控片段一起使用,我认为我正在正确创建一个键控片段(https:// Reactjs.org/docs/fragments.html#keyed-fragments)。任何帮助将不胜感激!
是的,但据我所知 - 您正在迭代
Outer
孩子。
尝试
React.Children.map(children[0].props.children, (child) => (
但是,仔细查看您的链接 - 我发现文档在这里说错了
该函数永远不会传递容器对象
这是一个示例,清楚地表明容器被传递给函数:
<script src="https://unpkg.com/@babel/standalone/babel.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="root" />
<script type="text/babel">
const Frag = () => (
<>
<div>test1</div>
<div>test2</div>
</>
);
const Outer = ({ children }) => (
<div>
{
React.Children.map(children, (child) => console.log(`Child type is ${child.type.name || child.type.toString()}`) || (
<a>
{child}
</a> ))
}
</div>
);
ReactDOM.render((
<div>
<Outer>
<>
<div>test1</div>
<div>test2</div>
</>
</Outer>
<Outer>
<Frag />
</Outer>
</div>
), document.getElementById('root'));
</script>
不要使用
React.Children.map
,而是使用此 flatMapChildren
函数来展平 <>fragments</>
以及数组:
import { Children } from 'react';
// TypeScript version
export function flatMapChildren<R>(children: React.ReactNode, fn: (x: React.ReactNode) => R) {
let results: R[] = [];
flatForEachChild(children, child => results.push(fn(child)));
return results;
}
export function flatForEachChild(children: React.ReactNode, action: (x: React.ReactNode) => void) {
if (isFragment(children)) {
flatForEachChild(children.props.children, action);
} else {
Children.forEach(children, child => {
if (isFragment(child))
flatForEachChild(child.props.children, action);
else
action(child);
});
}
}
const REACT_FRAGMENT = Symbol.for('react.fragment');
export function isFragment(node: React.ReactNode): node is React.ReactElement<{ children: React.ReactNode }> {
return (node as any)?.type === REACT_FRAGMENT;
}
// JavaScript version
export function flatForEachChild(children, action) {
if (isFragment(children)) {
flatForEachChild(children.props.children, action);
} else {
Children.forEach(children, child => {
if (isFragment(child))
flatForEachChild(child.props.children, action);
else
action(child);
});
}
}
export function flatMapChildren(children, fn) {
let results = [];
flatForEachChild(children, child => results.push(fn(child)));
return results;
}
const REACT_FRAGMENT = Symbol.for('react.fragment');
export function isFragment(node) {
return node != null && node.type === REACT_FRAGMENT;
}