react hooks 如何实现父组件调用子组件的方法? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaoming1992
V2EX    React

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

  •  1
     
  •   xiaoming1992 2020-06-03 00:13:48 +08:00 6703 次点击
    这是一个创建于 2032 天前的主题,其中的信息可能已经有所发展或是发生改变。

    两点前提:

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

    第 1 条附言    2020-06-03 08:50:05 +08:00
    讲一下问题的起因吧,我正在做一个翻纸牌的小游戏。
    有一大批纸牌,**我认为**每张纸牌应该有一定的的智慧和自主权决定自己是正面还是反面,从原则上来讲,我不想干涉它。我的做法是当子组件切换状态的时候通知父组件。

    可是从业务上讲,我又需要有能力(vip 功能),控制每一张牌的翻面。

    有朋友提到单向数据流,确实,如果直接由父组件指定每个子组件的状态,那这个问题根本就不是问题,可是因为是自己的玩具,所以我想任性一把(可是实力不允许)
    17 条回复    2020-11-26 05:22:39 +08:00
    fuermosi777
        1
    fuermosi777  
       2020-06-03 01:13:15 +08:00
    要不子组件还是 class 吧
    crs0910
        2
    crs0910  
       2020-06-03 03:31:04 +08:00 via iPhone
    为什么不把 theRightTime 作为 context 给子组件用呢
    crs0910
        3
    crs0910  
       2020-06-03 03:34:34 +08:00 via iPhone
    这个运动的声明好像是 Django rest api 的作者发起的,他们是直接把官方文档给换成了支持声明。react 只挂个横幅也算是很大支持了。
    ps4512
        4
    ps4512  
       2020-06-03 05:34:54 +08:00 via iPhone
    callback
    dartabe
        5
    dartabe  
       2020-06-03 05:48:00 +08:00
    react 不是应该单项数据流吗 你这个要求是不是应该把 function 直接放到父组件或者 util ?

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

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

    这两种选中方式互不影响,如何优雅的实现这一点呢?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2633 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 42ms UTC 12:10 PVG 20:10 LAX 04:10 JFK 07:10
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86