Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

使用 Hooks,当一个数组filter之后拿去渲染,会导致原数组改变 #5019

Closed
xiaoyuze88 opened this issue Dec 6, 2019 · 9 comments
Assignees

Comments

@xiaoyuze88
Copy link
Contributor

问题描述

(Taro版本1.3.26,使用 Hooks)当一个数组filter过后拿去渲染,会导致原始数组改变(业务代码没有任何写行为)

复现步骤

大概就是,有一个数组,需要根据筛选项过滤,但是切换几次过滤条件后原始数组会改变。

  1. 如果原始数组不用useState,而是写死变量,不会复现;
  2. 如果filter后的数组不拿来渲染dom,只是输出 JSON.stringify,不会复现;

image
image
image
image

import Taro, { useRef, useState } from '@tarojs/taro';
import { View, Button } from '@tarojs/components';

export default function Home() {
  const lastDeviceIdsRef = useRef('');
  const [deviceList] = useState([
    { DeviceId: '1', RoomId: '1' },
    { DeviceId: '2', RoomId: '1' },
    { DeviceId: '3', RoomId: '2' },
    { DeviceId: '4', RoomId: '3' },
    { DeviceId: '5', RoomId: '4' },
    { DeviceId: '6', RoomId: '4' },
    { DeviceId: '7', RoomId: '4' },
  ]);
  const [roomList] = useState([
    { RoomId: '1' },
    { RoomId: '2' },
    { RoomId: '3' },
    { RoomId: '4' },
  ]);
  const [roomId, setRoomId] = useState('');

  const deviceIds = deviceList.map(item => item.DeviceId).join('|');

  if (lastDeviceIdsRef.current !== deviceIds) {
    console.log('deviceList changed');
    console.log('prev: ', lastDeviceIdsRef.current);
    console.log('next: ', deviceIds);
    lastDeviceIdsRef.current = deviceIds;
  }


  return (
    <View>
      {roomList.map(item => (
        <Button
          style={{
            backgroundColor: item.RoomId === roomId ? 'red' : '',
          }}
          onClick={() => setRoomId(item.RoomId)}
        >{item.RoomId}</Button>
      ))}

      <View>
        originList:{JSON.stringify(deviceList.map(item => item.DeviceId))}
      </View>

      {/* 不渲染出dom就没事 */}
      {/* <View> */}
      {/*  seletedList:{JSON.stringify(deviceList */}
      {/*  .filter(item => item.RoomId === roomId) */}
      {/*  .map(item => item.DeviceId))} */}
      {/* </View> */}

      <View>
        seletedList:{deviceList
        .filter(item => !roomId || item.RoomId === roomId)
        .map(item => (
          <View>{item.DeviceId}</View>
        ))}
      </View>
    </View>
  );
}

期望行为

当然是不要改变原数组啊

报错信息

系统信息

👽 Taro v1.3.26

Taro CLI 1.3.26 environment info:
System:
OS: macOS 10.14
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 8.9.3 - /usr/local/bin/node
Yarn: 1.9.4 - /usr/local/bin/yarn
npm: 5.5.1 - /usr/local/bin/npm
npmPackages:
@tarojs/async-await: ^1.3.26 => 1.3.26
@tarojs/components: ^1.3.26 => 1.3.26
@tarojs/plugin-babel: ^1.3.26 => 1.3.26
@tarojs/plugin-csso: ^1.3.26 => 1.3.26
@tarojs/plugin-less: ^1.3.26 => 1.3.26
@tarojs/plugin-uglifyjs: ^1.3.26 => 1.3.26
@tarojs/redux: ^1.3.26 => 1.3.26
@tarojs/router: ^1.3.26 => 1.3.26
@tarojs/taro: ^1.3.26 => 1.3.26
@tarojs/taro-weapp: ^1.3.26 => 1.3.26
@tarojs/webpack-runner: ^1.3.26 => 1.3.26
eslint-config-taro: ^1.3.26 => 1.3.26
eslint-plugin-taro: ^1.3.26 => 1.3.26
nerv-devtools: ^1.5.0 => 1.5.1
nervjs: ^1.5.0 => 1.5.1
stylelint-config-taro-rn: ^1.3.26 => 1.3.26
stylelint-taro-rn: ^1.3.26 => 1.3.26
npmGlobalPackages:
typescript: 1.8.10

补充信息

如果您有功能上的建议,可以提到 FeatHub

使用上的问题,欢迎在「Taro 社区」一起交流

@taro-bot
Copy link

taro-bot bot commented Dec 6, 2019

CC @Chen-jj

@taro-bot
Copy link

taro-bot bot commented Dec 6, 2019

欢迎提交 Issue~

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

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

Good luck and happy coding~

@xiaoyuze88
Copy link
Contributor Author

发现要这样写,彻底隔绝原数组和新数组才不会影响,但是单纯filter不应该会动原数据才对呀

const list = [];

  deviceList.forEach((item) => {
    if (!roomId || item.RoomId === roomId) {
      // 这样都不行
      // list.push(item);
      list.push({ ...item });
    }
  });

@Garfield550
Copy link
Collaborator

你把 filter 写在 render 里面 return 外面,然后给 filter 的结果赋值到一个常量试一下

image

@xiaoyuze88
Copy link
Contributor Author

你把 filter 写在 render 里面 return 外面,然后给 filter 的结果赋值到一个常量试一下

image

一样的,看我上一条评论。哪怕不用filter,新建个数组,符合条件push原item进去都不行,必须要结构原item push进新数组才不会影响原数组

@Garfield550
Copy link
Collaborator

filter 返回的结果是一个新数组啊。

image

@xiaoyuze88
Copy link
Contributor Author

filter 返回的结果是一个新数组啊。

image

就是因为应该返回新数组,所以问为什么会导致原数组改变

@Garfield550
Copy link
Collaborator

啊,我理解有误

@Chen-jj
Copy link
Contributor

Chen-jj commented Dec 10, 2019

#5012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants