我正在编写一个自定义钩子,以将其与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]);
,因为这可能会占很大比例。
https://github.com/ferrannp/realm-react-native-hooks-stackoverflow
答案 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;
}