react-native - 子组件未在道具更改时重新渲染
问题描述
在以下代码中,我希望OfferList
在将商品添加到商店时重新呈现。OfferList
本身不是可观察的,但报价数组作为道具传递。
export const MerchantScreen: FC = observer(() => {
const { merchantStore } = useStores()
return (
<View>
<OfferList data={merchantStore.offers} />
<View>
<Button title={"New Offer"} onPress={() => merchantStore.addOffer()}/>
</View>
</View>
)
})
export const OfferList: FC<OfferListProps> = ({ data }: OfferListProps) => {
const renderItem = (offer: ListRenderItemInfo<any>) => {
return (
<Text>{offer.name}</Text>
)
}
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
)
}
我使用 Mobx 状态树。现在merchantStore.addOffer()
要做的就是将另一个报价项推送到数组中。
我尝试了什么/发现:
当我从我的商店阅读时MerchantScreen
,例如通过添加
<Text>{ merchantStore.offers.toString() }</Text>
,OfferList
也会更新。我怀疑直接在父组件中从商店读取也会强制重新渲染子组件。
我在这里偶然发现了一些答案,这表明key
FlatList renderItems 中缺少的属性可能是问题所在。尝试使用key={item.id}
无济于事。另外,如您所见,我使用了 FlatList 的 keyExtractor 属性。
另一个答案建议将本地状态引入组件,如下所示:
export const OfferList: FC<OfferListProps> = ({ data }: OfferListProps) => {
const [offers, setOfferss] = useState()
useEffect(() => {
setOffers(data)
}, [data])
const renderItem = (offer: ListRenderItemInfo<any>) => {
return (
<Text>{offer.name}</Text>
)
}
return (
<FlatList
data={offers}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
)
}
这不起作用,我的直觉是这不是它的完成方式。
如您所见,我的MerchantScreen
父组件是可观察的,而我的子组件OfferList
不是。根据我的期望,observer
我的父组件应该足够了。父组件应该已经检测到存储中的更改并重新渲染。子组件本身甚至不使用商店。
总的来说,手头的问题似乎很微不足道,所以我想我只是错过了一个重要的细节。
解决方案
MobX 只跟踪观察者组件访问的数据,如果它们被渲染直接访问,所以如果你想对每一个做出反应,offers
你需要在某个地方访问它们。当你尝试时,你有点做merchantStore.offers.toString()
,这就是它起作用的原因。
所以首先你需要制作OfferList
一个observer
.
但是你有FlatList
哪个是本机组件,你不能把它变成一个observer
. 你可以做的是访问offers
里面的每个项目OfferList
(基本上只是为了订阅更新),data={offers.slice()}
或者使用 MobX 辅助方法更好toJS
data={toJS(offers)}
根据您的用例,您可能还想<Observer>
在renderItem
回调中使用:
const renderItem = (offer: ListRenderItemInfo<any>) => {
return (
<Observer>{() => <Text>{offer.name}</Text>}</Observer>
)
}
推荐阅读
- android - 我正在研究在调试模式下工作但不在发布模式下工作的谷歌地图距离矩阵 API
- css - 响应式标题// 调整 img 大小和 img 上的文本
- python - 烧瓶会话:如何关闭会话中的资源
- angular - Angular - 如何在发布请求后使用订阅或地图中的数据并在对象中设置
- android - androidX AppCompatTextView justificationMode
- reporting-services - 累积数据系列在 Power BI 中的表中显示错误
- c# - 如何延迟像 QTimer::singleShot 这样的 C# 动作?
- jenkins - Groovy 脚本在 jenkins 上执行多个不同的作业而不使用管道?
- java - Spring Data Elasticsearch @Query 中的结果顺序
- java - Selenium Java中的setAttribute a href