如何使用 mobx-react-lite 使 child 组件对 mobx 中的状态变化做出反应
How to make child component reactive to state change in mobx using mobx-react-lite
我正在使用 mobx-state-tree 和 mobx-react-lite,谁能指导我找到更好的模式,
wishlist.js - 心愿单商店
import { types } from 'mobx-state-tree'
export const WishListItem = types.model('WishListItem', {
name: types.string,
price: types.number,
image: "",
}).actions(self => ({
changeName(newName) {
self.name = newName
},
}))
export const WishList = types.model('WishList', {
items: types.optional(types.array(WishListItem), []),
})
root.js - 根存储
export const RootStore = types.model('RootStore', {
counter: types.optional(Counter, { count: 0 }),
wishList: types.optional(WishList, {
items: [{ image: '', price: 10, name: 'Yoda' }]
}),
})
我正在将商店更新为
setInterval(() => store.wishList.items[0].changePrice(Math.random() * 100), 500)
在我的心愿单视图中
wishlist.jsx
const WishListItem = ({ image, name, price }) => {
return useObserver(
() =>
<div>
<img src={image} />
<h3>{name}</h3>
<h5>{price}</h5>
</div>
)
}
const WishListView = ({ items }) => {
return useObserver(
() => <>
{
items.map(
(item, key) => <WishListItem {...item} key={key} />
)
}
</>
)
}
export default () => useObserver(() => (
<WishListView items={store.wishList.items} />
))
这里我必须在组件树的每一层使用 useObserver
或 Observer
,以使其具有反应性,有什么方法可以将反应性引用传递给 child ?
对于字符串或数字等基本类型,它工作得很好,但是对于数组或 object,我必须直接引用 parent 处的变化变量,例如 store.wishList[0].price
或者在整棵树中使用 useObserver
。
我想将项目数组传递给 children,并更新 children 的变化,就在根部
export default () => useObserver(() => (
<WishListView items={store.wishList.items} />
))
不再使用 useObserver childrens
更新
我发现的解决方法是解构数组,现在更改是反应性的,因为我们直接访问正在更改的变量。
export default () => useObserver(() => {
const items = store.wishList.items.map(item => ({ ...item }))
return <WishListView items={items} />
})
and no more useObserver at it's childrens
如果可能的话,实际上最好将所有组件标记为observer
。例如,如果您将每个 Item
标记为观察者,并且其中一项更改了名称,则只有该组件会重新呈现。如果您不设置 Item
观察者,那么您的整个 List
将重新渲染,如果有很多项目或深 DOM 树,这将非常糟糕。当只有一个项目发生变化时,重新呈现整个列表也没有意义。
在这里查看解释https://mobx.js.org/refguide/observer-component.html#when-to-apply-observer
因此,您的解决方法是一种糟糕的做法,如果您无法控制子组件并且无法创建它们,则只能作为最后的手段使用 observer
。
我正在使用 mobx-state-tree 和 mobx-react-lite,谁能指导我找到更好的模式,
wishlist.js - 心愿单商店
import { types } from 'mobx-state-tree'
export const WishListItem = types.model('WishListItem', {
name: types.string,
price: types.number,
image: "",
}).actions(self => ({
changeName(newName) {
self.name = newName
},
}))
export const WishList = types.model('WishList', {
items: types.optional(types.array(WishListItem), []),
})
root.js - 根存储
export const RootStore = types.model('RootStore', {
counter: types.optional(Counter, { count: 0 }),
wishList: types.optional(WishList, {
items: [{ image: '', price: 10, name: 'Yoda' }]
}),
})
我正在将商店更新为
setInterval(() => store.wishList.items[0].changePrice(Math.random() * 100), 500)
在我的心愿单视图中 wishlist.jsx
const WishListItem = ({ image, name, price }) => {
return useObserver(
() =>
<div>
<img src={image} />
<h3>{name}</h3>
<h5>{price}</h5>
</div>
)
}
const WishListView = ({ items }) => {
return useObserver(
() => <>
{
items.map(
(item, key) => <WishListItem {...item} key={key} />
)
}
</>
)
}
export default () => useObserver(() => (
<WishListView items={store.wishList.items} />
))
这里我必须在组件树的每一层使用 useObserver
或 Observer
,以使其具有反应性,有什么方法可以将反应性引用传递给 child ?
对于字符串或数字等基本类型,它工作得很好,但是对于数组或 object,我必须直接引用 parent 处的变化变量,例如 store.wishList[0].price
或者在整棵树中使用 useObserver
。
我想将项目数组传递给 children,并更新 children 的变化,就在根部
export default () => useObserver(() => (
<WishListView items={store.wishList.items} />
))
不再使用 useObserver childrens
更新
我发现的解决方法是解构数组,现在更改是反应性的,因为我们直接访问正在更改的变量。
export default () => useObserver(() => {
const items = store.wishList.items.map(item => ({ ...item }))
return <WishListView items={items} />
})
and no more useObserver at it's childrens
如果可能的话,实际上最好将所有组件标记为observer
。例如,如果您将每个 Item
标记为观察者,并且其中一项更改了名称,则只有该组件会重新呈现。如果您不设置 Item
观察者,那么您的整个 List
将重新渲染,如果有很多项目或深 DOM 树,这将非常糟糕。当只有一个项目发生变化时,重新呈现整个列表也没有意义。
在这里查看解释https://mobx.js.org/refguide/observer-component.html#when-to-apply-observer
因此,您的解决方法是一种糟糕的做法,如果您无法控制子组件并且无法创建它们,则只能作为最后的手段使用 observer
。