Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

建议:使用 useImperativeHandle hook 代替 ref callback #109

Open
yzhiJun opened this issue Mar 23, 2020 · 2 comments
Open

建议:使用 useImperativeHandle hook 代替 ref callback #109

yzhiJun opened this issue Mar 23, 2020 · 2 comments

Comments

@yzhiJun
Copy link

yzhiJun commented Mar 23, 2020

背景

为了能在普通 JavaScript 函数中调用 <Notification ref={ref} /> 组件实例的方法,目前是通过 class componentref callback 机制实现的,但因为依赖异步回调,导致上层 API 的使用也深受回调影响,如果可以通过某种方式同步获得组件的控制权,那么在 API 使用和封装上会变得优雅很多:

const instance = Notification.newInstance();
const key = instance.add({title: 'xxx'}); // 可以同步返回 key
instance.remove(key);

我们可以通过 useImperativeHandle hook 结合 ref 转发来实现此需求。

大致思路:

  • 使用 Function Component 改写 Notification 组件
  • Notification 组件通过 useImperativeHandle hook 和 forwardRef 暴露内部 add 和 remove 方法
  • Notification.newInstance 通过 createRef 并把 ref.current 同步返回,这样就可以实现同步调用了
const Notification = React.forwardRef((props, ref) => {
  const [notices, setNotices] = useState([]);

  const add = notice => {
    // add notice
  };

  const remove = key => {
    // remove notice
  };

  // expose add & remove methods
  useImperativeHandle(ref, () => ({
    add,
    remove,
  }));

  return (
    <div>{noticeNodes}</div>
  );
});
Notification.newInstance = function newNotificationInstance(properties) {
  const ref = React.createRef();
  // append container stuff....
  ReactDOM.render(<ToastHub {...props} ref={ref} />, div);

  return {
    notice: noticeProps => ref.current.add(noticeProps),
    removeNotice: key => ref.current.remove(key),
    component: ref.current,
    destroy() {
      ReactDOM.unmountComponentAtNode(div);
      div.parentNode.removeChild(div);
    },
  };
}
@sage-z
Copy link

sage-z commented Jul 24, 2021

看了半天也没看出来 holderCallback 是为了干什么的,看了你的issue才明白是为了兼容老版本,谢谢!
目前已有hook实现


。。。其实也不能说是兼容,发现hook是基于holderCallback实现的

@afc163
Copy link
Member

afc163 commented Jul 26, 2021

欢迎 PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants