FlatList 未使用 React Hooks 和 Realm 更新

Fer*_*gre 5 reactjs react-native react-native-flatlist react-hooks

我正在编写一个自定义钩子以将它与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;
}
Run Code Online (Sandbox Code Playgroud)

在我的组件中:

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

  return (
    <View>
      <Text>{data.length}</Text>
      <FlatList
        data={data}
        keyExtractor={keyExtractor}
        renderItem={renderItem}
      />
    </View>
  );
};
Run Code Online (Sandbox Code Playgroud)

在前面的部分,在做的时候setData(newData),在data.length被正确地内的更新Text。但是,FlatList不会重新渲染,就像数据没有改变一样。

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

编辑 1

回购以重现它

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

小智 1

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

\n\n

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

\n\n
function useRealmResultsHook(collection) {\n  const [data, setData] = useState([]);\n\n  useEffect(\n    () => {\n      function handleChange(newCollection, changes) {\n        if (changes.insertions.length > 0 || changes.deletions.length > 0) {\n          setData(newCollection.map(item => item.id));\n        }\n      }\n\n      collection.addListener(handleChange);\n      return () => collection.removeListener(handleChange);\n    },\n    []\n  );\n\n  return data;\n}\n
Run Code Online (Sandbox Code Playgroud)\n