在一个列表中,当 selected item change 了,如何合适的捕捉到这个改变? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yazoox
V2EX    React

在一个列表中,当 selected item change 了,如何合适的捕捉到这个改变?

  •  
  •   yazoox 2021-07-01 11:43:21 +08:00 1897 次点击
    这是一个创建于 1570 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如图,比如,当前选中的是 "Category3 -> Layout1",因为选中了,所以有高亮背景显示,等等。

    如果此时,我选择了另外一个 Item, 比如“Category2 -> Layout2”,则,如何通知 Category3 -> Layout1 取消“选中”状态,然后 Category2 -> Layout2 则变为选中状态?

    本来我的想法是,在这个组件 /app 的全局,添加一个 selectedItem 和一个 previousSelectedItem 变量,专门用于维护”选中“状态,每次 有鼠标点击一个 Item 的时候,发送消息,改变 selected & previous selected item,再进行渲染。

    这样的话,我可能需要有一个 map, key 是 item's id, value 就是这个 item 对象。当 selected 对象改变时,通过这个 map,和 key 找到对应的 item,然后 改变它的 state,这样,react 就会只 re-render 这两个对象了,而不是 render 所有的 items.

    但感觉不是很”优雅“,所以,来请教一下大家。有没有更好的方法。

    谢谢!

    TreeView.png

    p.s.
    框架使用的是 react, redux or useReducer.

    第 1 条附言    2021-07-02 17:49:26 +08:00

    我在codesandbox上面写了一个简化的版本。 大家有兴趣可以看看!

    点击一个item后,会“选中”,显示方式是后面添加了5个*号。同时de-select上一次选中的item.

    但这个方法”不好“,每次点击,都会全部re-render,一共13次。我一直希望只re-rend两次。 大家打开console看log,会有输出。

    有没有高手,指点一二,谢谢!

    https://codesandbox.io/s/treeviewdemo-geb72

    Screen Shot.png

    8 条回复    2021-07-02 14:46:30 +08:00
    alfredhot
        1
    alfredhot  
       2021-07-01 12:37:26 +08:00
    所有 Category 下的每个 Layout 都赋不同的值,
    然后将 Click(或者 selecteItem)函数提升到上一级.
    用一个 selectedItem state 来控制状态就可以.
    不知到你说的是不是这个效果.

    下面的代码撸得匆忙, 瑕疵较多, 希望不要介意.

    https://gist.github.com/alfredhot/03bdcf17ec52e847211ed3bb11fa4b40


    还有就是, 为什么是 Cagetory ...
    Leviathann
        2
    Leviathann  
       2021-07-01 13:28:58 +08:00 via iPhone
    一般是把被选中的 item 由 item list 的上层组件维护
    lybcyd
        3
    lybcyd  
       2021-07-01 13:32:00 +08:00 via Android
    如果没有特殊需求,不需要保存前一个被点击的条目吧。只需要在树状组件维护一个叫 selected 的 state,用于保存被选中 layout 的 ID 。在循环渲染中,如果该 layout 被选中,传一个 active 为 true 的 prop,用于标记高亮就可以了。当进行点击时,触发一个 change 事件,把点击的 layout ID 作为参数传递,在树状组件处修改 selected 即可。
    yazoox
        4
    yazoox  
    OP
       2021-07-01 13:47:25 +08:00
    @alfredhot

    Category 仅仅只是一个名字,测试用例,别在意。其实,都是 TreeNode
    另,兄弟,你这个方法,每次有 selected item 变化,会全部重新渲染吧。这恰恰 就是我想避免的。因为列表可能会很大......
    alfredhot
        5
    alfredhot  
       2021-07-01 13:58:24 +08:00
    @yazoox

    原来如此, 我就说应该不是这么单纯的问题!
    我有空也得自己研究研究.
    sleepwalker
        6
    sleepwalker  
       2021-07-01 23:58:40 +08:00 via iPhone
    可以考虑利用单选框,然后用:checked 选择器来施加选中样式
    siweipancc
        7
    siweipancc  
       2021-07-02 09:09:36 +08:00 via iPhone
    state 对象过大需要 react-reducer,也能做到父子依赖解藕,主要是 ui 渲染别崩了
    yazoox
        8
    yazoox  
    OP
       2021-07-02 14:46:30 +08:00
    @siweipancc 兄弟,能详细说说么?或者有没有相关文档分享一下。谢谢
    我现在也使用了 useReducer, 和 context,在 tree 的根组件处,useReducer,然后把 selectedItem 作为 props 传给子组件。
    只要任何子组件的 onClick 触发了,就会 dispatch curent item,这样根组件就拿到当前 selectedItem,然后触发 re-render,再把 selectdItem 作为 props 传下去。

    可是,这样的话,依然有上面的问题。因为组件的 props 内容变化了( props.selecteItem 变了),所以,子组件都会触发 re-render 。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2753 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 09:15 PVG 17:15 LAX 02:15 JFK 05:15
    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