【发布时间】: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.length 在Text 中得到正确更新。但是,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