【问题标题】:React Native List item memoizationReact Native List 项目记忆
【发布时间】:2019-10-06 14:00:22
【问题描述】:

我正在尝试使用React.memo() 防止不必要的FlatList 项目呈现,但我遇到了一些奇怪的行为。提供前一个 props 和下一个 props 的回调始终具有相同的值,即使它们在链的更高位置发生了变化。

export default React.memo(PersonCell, (prev, next) => {
  reactotron.log(`prev ${prev.person.name}: is checked${prev.person.isChecked}`)
  reactotron.log(`next ${next.person.name}: is checked${next.person.isChecked}`)
  return prev.person.isChecked === next.person.isChecked
})

我拥有的链是我使用Realm{id:number, name:string, isChecked:boolean} 的非常简单的结构,每当他们点击单元格时,它就会写入领域,在应用程序的顶层我有一个数据更改的侦听器,然后设置状态以将其传播回列表

let [data, setData] = useState([]);

  useEffect(() => {
    let sub = person$.subscribe({
      next: collection => {
        reactotron.logImportant!(collection)
        setData([...data, ...collection.map(x => x)]);
      },
    });

这是单元格代码

import React from 'react';
import { Subject } from "rxjs";
import { useEffect } from "react";
import realm, { PersonSchema } from "./realm";
import { Person } from "./PersonsList";
import { View, TouchableOpacity, Text } from "react-native";
import reactotron from 'reactotron-react-native';

interface Props {
  person: Person
}
const onCheck$ = new Subject<number>();
const PersonCell: React.FC<Props> = props => {

  useEffect(() => {
    let sub = onCheck$.subscribe({
      next: x => {
        realm.write(() => {
          let person = realm.objectForPrimaryKey<Person>(PersonSchema.name, x);
          if (!person) return;
          person.isChecked = !person.isChecked;
        });
      },
    });
    return () => sub.unsubscribe;
  }, []);

  return (
    <View>
      <Text>{props.person.name}</Text>
      <TouchableOpacity onPress={() => onCheck$.next(props.person.id)}>
        <View
          style={{
            backgroundColor: props.person.isChecked
              ? 'rgb(255,1,1)'
              : 'rgb(1,1,255)',
            width: 20,
            height: 20,
          }}
        />
      </TouchableOpacity>
    </View>
  );
};

PersonCell.whyDidYouRender = true;

// export default React.memo(PersonCell)
export default React.memo(PersonCell, (prev, next) => {
  reactotron.log(`prev ${prev.person.name}: is checked${prev.person.isChecked}`)
  reactotron.log(`next ${next.person.name}: is checked${next.person.isChecked}`)
  return prev.person.isChecked === next.person.isChecked
})

这是预期的行为还是我做错了什么? Here is a repo 我在解释什么

更新

我删除了平面列表并使用基本地图和密钥生成项目列表,当前道具仍然出现上述问题,shouldComponentUpdateReact.memo第二个参数中传入的道具仍然完全正确一样的,尽管已经改变了。

here is a link 一个正在经历类似事情的人

【问题讨论】:

    标签: react-native memoization


    【解决方案1】:

    我认为问题是由于以非反应方式改变状态。我相信这个

    let sub = person$.subscribe({
          next: collection => {
            setData(collection.map(x => x));
          },
        });
    

    返回一个新数组就足够了(因为 map 返回一个全新的数组)以使用所需的更改比较来更新状态。但显然您需要执行以下操作。

    let sub = person$.subscribe({
          next: collection => {
            setData(collection.map(x => x).map(x => _.toPlainObject(x)));
          },
        });
    

    即对从领域返回的每个对象进行深度克隆,以使其正常工作......或者打字稿可能存在问题。

    如果有人想提供更简洁的答案,我们非常欢迎。

    如果有人想查看它,无论哪种方式,repo 都已随更改更新。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-10
      • 2020-09-19
      • 1970-01-01
      • 1970-01-01
      • 2021-10-17
      • 2021-12-04
      • 1970-01-01
      • 2018-01-06
      相关资源
      最近更新 更多