NervJS / taro

开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5/React Native 等应用。 https://taro.zone/
https://docs.taro.zone/
Other
35.6k stars 4.8k forks source link

props数组成员无法正常更新渲染 #5055

Closed zicjin closed 4 years ago

zicjin commented 4 years ago

问题描述

hook组件的props数组成员无法正常更新渲染

复现步骤

最简化demo: https://github.com/zicjin/taro-test 使用标准项目新建流程。typescript,无css预处理。

export default function Shelves(props) {
  const { specs = [] } = props

  // const specs = [{
  //   'id': 482,
  //   'detail': [],
  //   'price': 30,
  //   'platformPrice': 10,
  //   'profit': 20,
  //   'marketPrice': 25,
  //   'stock': 480,
  //   'commissionRate': null
  // }]

  const [profits, setProfits] = useState(specs.map(s => ({
    specId: s.id,
    profit: 0
  })))

  const setProfit = (e, i) => {
    profits[i].profit = +e.detail.value
    setProfits([...profits])
  }

  return (
    <View className='shelves' style={{ marginBottom: '100px' }}>
      {specs.map((s, i) => <View key={i}>
        <Input
          type='number'
          value={profits[i].profit}
          onInput={e => { setProfit(e, i) }}
        />

        {/* confuse: 无法移除 toString() */}
        <View style={{ marginTop: '20px' }}>{profits[i].profit}</View>
        <View>{profits[i].profit.toString()}</View>

      </View>)}
    </View>
  )
}

当我更改input值,“profits[i].profit”无法正常更新。以下情况可正常更新:

  1. 加上toString()即可正常。
  2. 使用组件内部变量代替 props.specs 即可正常
  3. props.specs 更换为object,修改useState(specs.map... 即可正常
  4. 纯react应用也没有问题:https://codesandbox.io/s/jolly-wescoff-1y633?fontsize=14&hidenavigation=1

系统信息

Taro v1.3.27 Taro CLI 1.3.27 environment info: System: OS: Windows 10 Binaries: Node: 13.0.1 - C:\Program Files\nodejs\node.EXE npm: 6.13.0 - C:\Program Files\nodejs\npm.CMD

taro-bot[bot] commented 4 years ago

CC @Chen-jj

taro-bot[bot] commented 4 years ago

欢迎提交 Issue~

如果你提交的是 bug 报告,请务必遵循 Issue 模板的规范,尽量用简洁的语言描述你的问题,最好能提供一个稳定简单的复现。🙏🙏🙏

如果你的信息提供过于模糊或不足,或者已经其他 issue 已经存在相关内容,你的 issue 有可能会被关闭。

Good luck and happy coding~

dxd1102 commented 4 years ago

userState 真正响应的是新生成的对象,你去改数组里的数据肯定不会变啊. `const a = specs.map(s => ({ specId: s.id, profit: 0 })) useState(a)

a[0].specId = 1111 `

zicjin commented 4 years ago

@dxd1102 你可以看codesandbox demo: https://codesandbox.io/s/jolly-wescoff-1y633?fontsize=14&hidenavigation=1 数组解构是完全可以更新的,这和本问题无关。看起来与 https://github.com/NervJS/taro/issues/4994 是同一个问题,太严重的问题了,希望taro项目一定要有单测流程。

dreamthen commented 4 years ago

{list: [{like: false}]}数组对象里面的对象属性值like变了,变成了true,这时候我返回一个新的对象,新的对象里面的数据是变掉了,{list:[{like: true}]},但是页面并没有刷新,还是原来的效果,这就是问题所在。

zicjin commented 4 years ago

@dreamthen 这根本不是本问题所在。请问为什么加上toString()页面就更新了? 另外请看react应用demo: https://codesandbox.io/s/jolly-wescoff-1y633?fontsize=14&hidenavigation=1

Chen-jj commented 4 years ago

5012

dreamthen commented 4 years ago

@zicjin 好像已经解决了

zicjin commented 4 years ago

至少发了1.3.28再close吧

dreamthen commented 4 years ago

1.3.27已经可以了,我刚刚试过了

zicjin commented 4 years ago

@dreamthen 我的最简化demo就是1.3.27。 https://www.npmjs.com/package/@tarojs/taro-weapp 7天前publish的。

dreamthen commented 4 years ago

https://github.com/NervJS/taro/commit/0892241461a72318fde4e5a3e7298101b26d113b @zicjin 他是刚刚直接push的master