FlatList不使用React Hooks和Realm更新

时间:2019-04-18 07:41:01

标签: 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;
}

在我的组件中:

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

1 个答案:

答案 0 :(得分: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;
}