V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hi20151215x
V2EX  ›  程序员

求助一下关于 react 更新 list 的一个疑问。

  •  
  •   hi20151215x · 2022-07-26 15:43:48 +08:00 · 1517 次点击
    这是一个创建于 630 天前的主题,其中的信息可能已经有所发展或是发生改变。
    	TodoList.map((item,index)=>{
        	return <Todo key=index total=TodoList.length>
        })
        
    

    现状:子组件 Todo 获取到的 total 值 分别是 1,2,3.....

    想要获得的结果:每当 List 更新时,所有子组件的 total 也都更新(所有子组建的 total 项一致,并且和 TodoList.length 相同)。

    在 google 用英文搜索好些结果,但因为英文描述问题,总是找不到确切的答案。 :) thanks in advance

    第 1 条附言  ·  2022-07-26 17:08:47 +08:00
      const [todoList,setTodoList] = useState([])
    
      const clickHandler=()=>{
        setTodoList([...todoList,'new todo!'])
      }
      return (
        <View>
          <Button onClick={()=>clickHandler()}>click to add new Todo.</Button>
          
          {todoList.map((item,index)=>{
              return <View><Todo content={item} size={todoList.length}></Todo></View>
          })}
    
        </View>
      )
    
    内容:new todo TodoList尺寸:1
    内容:new todo TodoList尺寸:2
    内容:new todo TodoList尺寸:3
    内容:new todo TodoList尺寸:4
    内容:new todo TodoList尺寸:5
    
    

    而期望得到的结果是

    内容:new todo TodoList尺寸:5
    内容:new todo TodoList尺寸:5
    内容:new todo TodoList尺寸:5
    内容:new todo TodoList尺寸:5
    内容:new todo TodoList尺寸:5
    
    
    第 2 条附言  ·  2022-07-26 17:45:14 +08:00

    todo 组件的代码

    function Todo(props) {
    
        const [content, setContent] = useState()
        const [size, setSize] = useState()
        useEffect(()=>{
            setContent(props.content)
            setSize(props.size)
        },[content,size])
    
      return (
        <View>内容:{content} TodoList尺寸:{size}</View>
      )
    }
    
    
    27 条回复    2022-07-27 10:19:45 +08:00
    happyeveryday
        1
    happyeveryday  
       2022-07-26 15:59:03 +08:00
    不就是 react 最基础的如何更新 state 然后 rerender 嘛...
    codehz
        2
    codehz  
       2022-07-26 16:05:18 +08:00
    (你不会直接原地 push 到数组的吧
    hi20151215x
        3
    hi20151215x  
    OP
       2022-07-26 16:05:59 +08:00
    @happyeveryday 每次新添加 todo 到 list 都能够 re-render 。 但就是结果不是想要的
    hi20151215x
        4
    hi20151215x  
    OP
       2022-07-26 16:06:29 +08:00
    @codehz 嗯。。是的。难道???问题在这里?
    Leviathann
        5
    Leviathann  
       2022-07-26 16:09:11 +08:00
    key 不要设为 index
    ryncv
        6
    ryncv  
       2022-07-26 16:16:37 +08:00
    setState({TodoList: [...TodoList]})
    wenzichel
        7
    wenzichel  
       2022-07-26 16:34:17 +08:00
    无论是类组件还是函数组件,不要直接操作 TodoList 。

    在类组件中,是使用 this.setState()来操作的;在函数组件里,是用 const [TodoList, setTodoList] = useState()这个 hook 中的第 2 个参数 setTodoList()来操作的。
    yaphets666
        8
    yaphets666  
       2022-07-26 16:53:22 +08:00
    vue 里直接 push 就行,react 不是这个套路
    pengtdyd
        9
    pengtdyd  
       2022-07-26 17:07:03 +08:00
    key 不要设为 index ,key 会被动态赋值,导致不可预知的 bug
    Alander
        10
    Alander  
       2022-07-26 17:16:39 +08:00
    乍一看 append 的代码我竟看不出来这段代码是否真的会如作者所说的 1 ,2 ,3 ,4 ,5
    应该全是 5 才对
    fengfuliu
        11
    fengfuliu  
       2022-07-26 17:17:50 +08:00
    setTodoList([...todoList,'new todo!'])改成 setTodoList(prev=>([...prev,'new todo!']))
    hi20151215x
        12
    hi20151215x  
    OP
       2022-07-26 17:18:34 +08:00
    @Alander 如果在当前组件 全是 5 ,但是传递到子组件后 就不是了。
    zhangdroid
        13
    zhangdroid  
       2022-07-26 17:23:37 +08:00
    append 的代码应该是可以得到预期的结果的, 有问题的话有可能是 Todo 这个组件有问题, 比如用了 memo/shouldComponentUpdate
    Alander
        14
    Alander  
       2022-07-26 17:30:51 +08:00
    @hi20151215x 如 13 楼所说,希望能贴出来 Todo 组件的代码才能更好的知道为什么。至于纠正你如何去 setState 的可以忽略
    Alander
        15
    Alander  
       2022-07-26 17:32:04 +08:00
    @hi20151215x 确实是不应该直接 push ,但是你 append 后的代码更新方式已经是正确更新方式了,所以直接看一下 Todo 组件的代码应该可以发现端倪
    churchill
        16
    churchill  
       2022-07-26 17:36:26 +08:00
    你是不是在🎣啊
    hi20151215x
        17
    hi20151215x  
    OP
       2022-07-26 17:45:37 +08:00
    @churchill 都快抓耳挠腮了。
    hi20151215x
        18
    hi20151215x  
    OP
       2022-07-26 17:46:16 +08:00
    @Alander 代码已更新 希望得到您回复:)
    codehz
        19
    codehz  
       2022-07-26 17:47:39 +08:00
    咦 ,
    const [content, setContent] = useState()
    const [size, setSize] = useState()
    useEffect(()=>{
    setContent(props.content)
    setSize(props.size)
    },[content,size])
    这是在干啥
    用内部的 state 作为 effect 的 deps 参数吗,那肯定不会更新啊(另外推荐开 eslint
    直接在 jsx 里用 props 上的属性就可以了
    westoy
        20
    westoy  
       2022-07-26 17:55:07 +08:00
    Todo 加个 key={`item-${index}-${todoList.length}`}
    freeman12
        21
    freeman12  
       2022-07-26 17:56:11 +08:00
    子组件直接 props.size 用就好了,干嘛存到自己的 state
    freeman12
        22
    freeman12  
       2022-07-26 17:56:47 +08:00
    这样<View>内容:{content} TodoList 尺寸:{props.size}</View>
    silk
        23
    silk  
       2022-07-26 17:57:41 +08:00
    ,[content,size] 去掉观察目标 有变化就更新 或者按照#19
    yunyuyuan
        24
    yunyuyuan  
       2022-07-26 18:19:25 +08:00
    你 todo 组件 useEffect 的依赖填错了,应该是 props.content 和 props.size ,而且这样写是脱裤子放屁。。。
    hi20151215x
        25
    hi20151215x  
    OP
       2022-07-26 18:22:25 +08:00
    @codehz
    @westoy
    @freeman12
    @silk
    谢谢大家 问题已经解决啦。使用了 freeman12 的主意 :) 🙏感谢
    shakukansp
        26
    shakukansp  
       2022-07-26 18:29:47 +08:00
    props 变动可以触发组件重渲染,所以
    function Todo(props) {
    return (
    <View>内容:{props.content} TodoList 尺寸:{props.size}</View>
    )
    }
    Envov
        27
    Envov  
       2022-07-27 10:19:45 +08:00
    useEffect(() => {
    setContent(props.content);
    setSize(props.size);
    }, [content, size]);
    这个依赖项写错了,导致结果是 useEffect 内的函数不会执行
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   966 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 20:30 · PVG 04:30 · LAX 13:30 · JFK 16:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.