我有几个功能组件:
export default function IconModal({
label,
icon,
className,
children
}) {
const el = useRef();
const [ isExpanded, setExpanded ] = useState(false);
const onClickOutside = useCallback(() => setExpanded(false), []);
const cx = classNames('modal__wrapper', className);
useOnClickOutside(el, onClickOutside);
return (
<div className={cx} aria-expanded={isExpanded} ref={el}>
<button onClick={() => setExpanded(!isExpanded)}
aria-label={label}
className="modal__action">
<Icon name={icon} />
</button>
<span className="modal">
<button className="modal__close" onClick={() => setExpanded(false)}>
<Icon name="close"/>
</button>
{children}
</span>
</div>
);
}
然后我打算像这样食用它:
export default function InfoIconModal() {
const context = useContext(SomeContext);
const title = 'Hey Here';
return (
<IconModal
className="header__modal__wrapper--info"
label="Know more about this"
icon="info"
>
<h2 className="info__subtitle text--uppercase">How This Works</h2>
<h3 className="info__title">{title} = {context.name}</h3>
<div className="info__body" dangerouslySetInnerHTML={{__html: context.hiw}} />
<p className="font--semi-bold">
<a href="#" target="_blank">View Legend</a>
</p>
</IconModal>
);
}
哪个效果很好。现在出现了一个事实,就是在这种情况下,如果用户单击“查看图例”链接,我想关闭模式,但这可能是任何其他原因。
我该如何实现?
答案 0 :(得分:2)
我认为这是export default function InfoIconModal() {
const context = useContext(SomeContext);
const title = 'Hey Here';
return (
<IconModal
className="header__modal__wrapper--info"
label="Know more about this"
icon="info"
>
{
({onClose}) => (
<h2 className="info__subtitle text--uppercase">How This Works</h2>
<h3 className="info__title">{title} = {context.name}</h3>
<div className="info__body" dangerouslySetInnerHTML={{__html: context.hiw}} />
<p className="font--semi-bold">
<a href="#" target="_blank" onClick={() => onClose()}>View Legend</a>
</p>
)
}
</IconModal>
);
}
export default function IconModal({
label,
icon,
className,
children
}) {
const el = useRef();
const [ isExpanded, setExpanded ] = useState(false);
const onClickOutside = useCallback(() => setExpanded(false), []);
const cx = classNames('modal__wrapper', className);
useOnClickOutside(el, onClickOutside);
return (
<div className={cx} aria-expanded={isExpanded} ref={el}>
<button onClick={() => setExpanded(!isExpanded)}
aria-label={label}
className="modal__action">
<Icon name={icon} />
</button>
<span className="modal">
<button className="modal__close" onClick={() => setExpanded(false)}>
<Icon name="close"/>
</button>
{children({onClose: () => setExpanded(isExpanded => !isExpanded)})}
</span>
</div>
);
}
模式的好用例,就像这样:
{{1}}
答案 1 :(得分:0)
这里的主要问题是必须为特定的onClick
添加一些道具(例如ReactElement
),因为您必须显式地或动态地进行操作。
直接的方法是使用常规的IconModal
回调在onClick
中呈现子级。
export default function IconModal(...) {
...
return (
<div >
...
<span>
<p onClick={ /* close modal */ }>
<a>
View Legend
</a>
</p>
</span>
</div>
);
}
或者您可以映射组件的子代并使用React.Children
和React.cloneElement
API添加其他属性。
export default function IconModal({ children, ... }) {
...
const childrenWithAdditionalProps = React.Children.map(children,
child => React.cloneElement(child, { /* Additional Props */ }))
return (
<div>
...
<span>
{childrenWithAdditionalProps}
</span>
</div>
);
}
为此,我认为您应该添加其他属性来标识要向其添加道具的组件,例如:
const additionalTriggers = {
legend: () => console.log("hello")
};
export default function InfoIconModal() {
return (
<IconModal
// v Tell your component which props you want to add
additionalTriggers={additionalTriggers}
>
// v Add id and check it when mapping
<p id="legend">
<a>View Legend</a>
</p>
</IconModal>
);
}