我正在使用react,我有一个组件,它只需要呈现孩子并根据条件为他们添加一个类。做这件事的最好方法是什么?
sbtkgmzw1#
我一周前就想明白了,这就是我想要的:
export default class ContainerComponent extends React.Component { constructor(props) { super(props); this.modifyChildren = this.modifyChildren.bind(this); } modifyChildren(child) { const className = classNames( child.props.className, {...otherClassses} ); const props = { className }; return React.cloneElement(child, props); } render() { return (<div> {React.Children.map(this.props.children, child => this.modifyChildren(child))} </div>); } }
50few1ms2#
为了简单起见:
const StyleInjector = ({ children }) => { const StyledChildren = () => React.Children.map(children, child => React.cloneElement(child, { className: `${child.props.className} ${PUT_YOUR_CLASS_HERE}` }) ); return <StyledChildren />; };
zf9nrax13#
几周前,我有一个狂欢的场景要在react中实现,没有什么花哨的,只是简单的切换活动类。我遵循了这个方法,工作起来很有魅力,但让我知道这是一个很好的方法。
{ this.props.children.map((slide, index) => { return React.cloneElement(slide, { key: index, className: (this.state.currentActiveIndex === index) ?'active' : '' }); }) }
wz1wpwve4#
你可以传递一个prop给child,它可以选择要应用的类(或者只传递类名,但这更语义化):
<Parent contentVisible={true}> <Child /> </Parent>
在子渲染中:
const classes = []; if (props.contentVisible) classes.push('visible'); <div className={classes.join(' ')} />
zqdjd7g95#
这是类型安全的现代解决方案(Typescript 5.0,React 18.2):
import * as React from 'react'; import type { ReactNode, ReactElement, ReactPortal, PromiseLikeOfReactNode, ReactFragment } from 'react'; type StylizeChildrenProps = { children?: ReactNode className: React.HTMLAttributes<any>['className'] } export function StylizeChildren({ children, className = '' }: StylizeChildrenProps) { if (children == null) return null; className = className.trim(); if (!className) return <>{children}</> return <> {React.Children.map(children, child => addClassToNode(child, className))} </> } // Separate out into its own function because Promise-like nodes require this to be recursive export function addClassToNode(node: ReactNode, className: string): ReactNode { if (node == null) { node satisfies null | undefined return node } if (typeof node !== 'object') { node satisfies string | number | boolean // wrap in a span, somewhat arbitrary decision return <span className={className}>{node}</span> } if ('props' in node) { node satisfies ReactElement | ReactPortal // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access const existing: unknown = node?.props?.className; if (existing && typeof existing === 'string') { className = `${existing} ${className}` } return React.cloneElement(node, { className }) } if ('then' in node) { node satisfies PromiseLikeOfReactNode return node.then(n => addClassToNode(n, className)) } node satisfies ReactFragment // wrap in div, somewhat arbitrary decision return <div className={className}>{node}</div> }
当它遇到非对象类型或ReactFragments时,可以直接修改它来做其他事情。例如,一个ReactFragment是一个Iterable,所以你可以迭代它的所有子元素,并给予它一个类,而不是把它 Package 在一个div中。satisfies语句之所以存在,是因为我认为它们更清楚地说明了正在发生的事情,并且如果底层类型或React API发生变化,它们将揭示一些其他令人讨厌的错误。如果您运行的是低于4.9的Typescript版本,只需删除它们,一切都应该正常工作。
satisfies
wz8daaqr6#
组件的内部渲染方法:
var childClasses = [], childClassNames; if (condition) { childClasses.push('my-class-name'); } childClassNames = childClasses.join(' '); return (<div className={childClassNames}> .... (your component here) </div> );
6条答案
按热度按时间sbtkgmzw1#
我一周前就想明白了,这就是我想要的:
50few1ms2#
为了简单起见:
zf9nrax13#
几周前,我有一个狂欢的场景要在react中实现,没有什么花哨的,只是简单的切换活动类。我遵循了这个方法,工作起来很有魅力,但让我知道这是一个很好的方法。
wz1wpwve4#
你可以传递一个prop给child,它可以选择要应用的类(或者只传递类名,但这更语义化):
在子渲染中:
zqdjd7g95#
这是类型安全的现代解决方案(Typescript 5.0,React 18.2):
当它遇到非对象类型或ReactFragments时,可以直接修改它来做其他事情。例如,一个ReactFragment是一个Iterable,所以你可以迭代它的所有子元素,并给予它一个类,而不是把它 Package 在一个div中。
satisfies
语句之所以存在,是因为我认为它们更清楚地说明了正在发生的事情,并且如果底层类型或React API发生变化,它们将揭示一些其他令人讨厌的错误。如果您运行的是低于4.9的Typescript版本,只需删除它们,一切都应该正常工作。wz8daaqr6#
组件的内部渲染方法: