react hooks 如何实现父组件调用子组件的方法?

2020-06-03 00:13:48 +08:00
 xiaoming1992

两点前提:

  1. 函数式组件, 使用 react hooks
  2. 子组件导出方法, 供父组件在恰当的时机(想什么时候就什么时候)调用

我唯一想到的方法是使用 ref, 如下, 但是这也太 TM 丑了, 求助大佬们

type ChildFunc = () => number

// eslint-disable-next-line react/display-name
const Child = React.forwardRef((props, ref) => {

  // eslint-disable-next-line no-param-reassign
  (ref as React.MutableRefObject<ChildFunc | undefined>).current = () => 5

  return <>I am child</>
})

// Parent
function Parent() {
  const funcRef = useRef<ChildFunc>()

  const theRightTime = new Promise((resolve) => {
    setTimeout(resolve, 1000)
  })

  useEffect(() => {
    theRightTime.then(() => {
      if (funcRef.current) {
        console.log(funcRef.current())
      }
    })
  }, [funcRef, theRightTime])

  return <Child ref={funcRef} />
}

顺便提一嘴, react 官网顶部有个"条幅" -- "黑人的命也是命。 支持公正司法倡议。" -- 但是各位可以切换语言看一下, 好像只有简体中文和英文有, 繁体中文、日文等都没有(那么多语言, 我也没一个一个翻, 但是我看了的好几个都没有)

5949 次点击
所在节点    React
17 条回复
fuermosi777
2020-06-03 01:13:15 +08:00
要不子组件还是 class 吧
crs0910
2020-06-03 03:31:04 +08:00
为什么不把 theRightTime 作为 context 给子组件用呢
crs0910
2020-06-03 03:34:34 +08:00
这个运动的声明好像是 Django rest api 的作者发起的,他们是直接把官方文档给换成了支持声明。react 只挂个横幅也算是很大支持了。
ps4512
2020-06-03 05:34:54 +08:00
callback
dartabe
2020-06-03 05:48:00 +08:00
react 不是应该单项数据流吗 你这个要求是不是应该把 function 直接放到父组件或者 util ?

我是菜鸟哈
WittBulter
2020-06-03 06:40:20 +08:00
React 有一个 useImperativeHandle 允许你用 hooks 的方式向外部暴露指定的实例属性或方法。

给你写了一个在线示例可以参考: https://codesandbox.io/s/invoker-child-methdos-gtwch?file=/src/app.js
ChefIsAwesome
2020-06-03 08:28:52 +08:00
传 ref 本质上就是传了个 onLoad 函数给子组件。子组件 mount 之后调这个函数,并且把它自己传进去。
你这个子组件提供方法的问题是一个道理。
xiaoming1992
2020-06-03 09:27:26 +08:00
@fuermosi777 我其他功能和样式都写完了,不想改了啊 T.T
@crs0910 这个 theRightTime 只是表明,在恰当的时机,由父组件触发而已,本质上还是说父组件需要在恰当的时机调用子组件的方法啊
@ps4512 跟 callback 应该没什么关系吧
@dartabe 确实放到父组件就没有这些问题了,只是有些私心,可以看看我 append 的内容
@WittBulter 这个 hook 我倒是确实不知道,涨姿势了,感谢(但是说实话,这样还是不够"优雅"啊...)
@ChefIsAwesome 不管是 ref 也好,全局变量也好,目前来看虽然勉强能实现,但是都有些丑,6L 的应该算是目前最佳的了
xiaoming1992
2020-06-03 09:30:02 +08:00
@WittBulter 不对,仔细看了一下,应该还是比较优雅的,比较完美贴合我这个需求的
hantsy
2020-06-03 15:37:59 +08:00
BlackLivesmatter 现在闹得比疫情还严重,不光是美国,欧洲也开始打杂抢了。
KuroNekoFan
2020-06-04 12:30:39 +08:00
方法很多比如
父组件改子组件的 props 然后子组件把这个 props 作为 dependency 来触发行为
LeoooY
2020-06-04 13:04:42 +08:00
我一般是把子组件封装成一个 useXXX(),然后 return dom 和需要调用的方法
const useChild=()=>{
return {
}
}
LeoooY
2020-06-04 13:05:38 +08:00
我一般是把子组件封装成一个 useXXX(),然后 return dom 和需要调用的方法
const useChild=()=>{
return {
dom: <child />
methods:{}
}
}
xiaoming1992
2020-06-04 15:06:28 +08:00
@LeoooY 这倒是一个好方法,我当时怎么没想到呢。。。我已经把原来由子组件控制的属性大部分移到父组件了。。。
xiaoming1992
2020-06-04 15:09:34 +08:00
@KuroNekoFan 可能不太行吧?之所以说希望子组件暴露出函数,就是因为函数用起来方便且语义明晰,用属性可能在这两方面不太合适吧?
KuroNekoFan
2020-06-04 17:31:23 +08:00
@xiaoming1992 所谓'子组件暴露出函数',react 是不希望开发者这样做的
https://zh-hans.reactjs.org/docs/hooks-reference.html#useimperativehandle 官方文档也说了,应当避免
除了我说的用 props 控制,还可以用事件,状态管理之类的
gamesover
2020-11-26 05:22:39 +08:00
我有类似的 user case
假设有一个 list 的 input checkbox,value 是从 1 到 10
这些 checkbox 本身是可以自由 check 或者 uncheck 的

但是我又希望提供一个范围比如 3 和 6,然后用户点击一个选择按钮,选中范围在 3 到 6 之间的 checkbox

这两种选中方式互不影响,如何优雅的实现这一点呢?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/678059

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX