如何从React的父组件获取功能

时间:2019-09-10 16:28:09

标签: javascript reactjs

我有几个功能组件:

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>
    );
}

哪个效果很好。现在出现了一个事实,就是在这种情况下,如果用户单击“查看图例”链接,我想关闭模式,但这可能是任何其他原因。

我该如何实现?

2 个答案:

答案 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}}

了解更多:https://reactjs.org/docs/render-props.html

答案 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.ChildrenReact.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>
  );
}