道具变更时未重新呈现子组件

时间:2020-09-26 16:56:53

标签: react-native mobx mobx-state-tree

在以下代码中,当我向商店添加商品时,我希望OfferList重新呈现。 OfferList本身不是可观察的,但是offer数组作为prop传递。

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也将更新。我怀疑直接从父组件中的商店读取内容也会迫使子组件重新呈现。

我在这里偶然发现了一些答案,这表明可能是FlatList renderItems中缺少key属性的问题。尝试使用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应该足够了。父组件应该已经在存储中检测到更改并重新呈现。子组件本身甚至不使用商店。

总体而言,眼前的问题似乎微不足道,所以我想我只是漏掉了一个重要的细节。

1 个答案:

答案 0 :(得分:2)

MobX仅跟踪通过渲染直接访问观察者组件的数据,因此,如果您想对每个offers做出反应,则需要在某个地方访问它们。尝试merchantStore.offers.toString()时您确实做了一下,这就是它起作用的原因。

因此,首先需要将OfferList设为observer

但是您拥有FlatList这是本机组件,因此无法将其设为observer。您可以做的就是访问offersOfferList内的每个data={offers.slice()}项目(基本上只是为了订阅更新),甚至可以使用MobX辅助方法toJS {{1 }}

根据您的用例,您可能还想在data={toJS(offers)}回调中使用<Observer>

renderItem