【问题标题】:FlatList not updating with React Hooks and RealmFlatList 未使用 React Hooks 和 Realm 更新
【发布时间】:2019-09-08 12:15:46
【问题描述】:

我正在编写一个自定义挂钩以将其与realm-js 一起使用。

export default function useRealmResultsHook<T>(query, args): Array<T> {
  const [data, setData] = useState([]);

  useEffect(
    () => {
      function handleChange(newData: Array<T>) {
        // This does not update FlatList, but setData([...newData]) does
        setData(newData);
      }

      const dataQuery = args ? query(...args) : query();
      dataQuery.addListener(handleChange);
      return () => {
        dataQuery.removeAllListeners();
      };
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [query, ...args]
  );

  return data;
}

在我的组件中:

const MyComponent = (props: Props) => {
  const data = useRealmResultsHook(getDataByType, [props.type]);

  return (
    <View>
      <Text>{data.length}</Text>
      <FlatList
        data={data}
        keyExtractor={keyExtractor}
        renderItem={renderItem}
      />
    </View>
  );
};

在前面的组件中,当执行setData(newData) 时,data.lengthText 中得到正确更新。但是,FlatList 不会重新渲染,就像数据没有改变一样。

我之前使用了一个 HOC 和一个具有相同行为的渲染道具,它按预期工作。难道我做错了什么?我想避免克隆数据setData([...newData]);,因为这可能是大量数据。

编辑 1

回购以重现它

https://github.com/ferrannp/realm-react-native-hooks-stackoverflow

【问题讨论】:

  • FlatList 是一个PureComponent,因此它需要一个全新的数组引用作为data 才能重新渲染。我不确定 Realm 是如何工作的,但 newData 可能是同一个数组但发生了变异?在handleChange 中尝试console.log(newData === data);,看看你会得到什么。如果是true,你必须像你在评论中写的那样做setData([...newData])。注意[...newData] 只会创建数组的浅拷贝;它里面的所有元素都将保持不变。
  • 如果你根据数据的一些散列给出一个密钥,你可能可以实现所需的行为
  • @Tholle 这就是我的想法,但console.warn(data === newData); 返回false。所以我真的不知道为什么FlatList 在这种情况下没有注意到它......它可以使用HOC 或渲染道具。
  • 嗯,很有趣。我知道涉及数据库会很困难,但也许你可以创建一个Minimal, Complete, and Verifiable example?这将使调查更容易。
  • 我创建了一个 repo 来复制它github.com/ferrannp/realm-react-native-hooks-stackoverflow。这是整个主文件github.com/ferrannp/realm-react-native-hooks-stackoverflow/blob/…。我什至不必使用FlatList,只是尝试使用Text 来显示结果的长度。

标签: reactjs react-native react-native-flatlist react-hooks


【解决方案1】:

处理程序中的初始data 变量和newData arg 是指向同一集合的链接。所以它们是相等的,setData(newData) 在这种情况下不会触发组件的重新渲染。

将 Realm 集合映射到项目 ID 数组可能会有所帮助。因此,您将始终拥有处于 React 状态的新数组,并且渲染将正确进行。仅检查集合的删除和插入以避免额外的列表重新呈现也很有用。但在这种情况下,您还应该为项目添加侦听器。

function useRealmResultsHook(collection) {
  const [data, setData] = useState([]);

  useEffect(
    () => {
      function handleChange(newCollection, changes) {
        if (changes.insertions.length > 0 || changes.deletions.length > 0) {
          setData(newCollection.map(item => item.id));
        }
      }

      collection.addListener(handleChange);
      return () => collection.removeListener(handleChange);
    },
    []
  );

  return data;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-08
    • 2020-01-29
    • 2021-11-08
    • 2019-09-15
    • 1970-01-01
    • 2020-06-19
    相关资源
    最近更新 更多