【发布时间】:2020-04-03 23:37:59
【问题描述】:
我正在使用 TypeScript、钩子和 mobx-react-lite 开始使用新的 create-react-app 应用程序。尽管过去在 React Native 应用程序中广泛使用过 MobX,但我遇到了一个对我来说没有任何意义的问题。
我有一个商店,里面有两个 observable:一个数字和一个布尔值。有一个 initialize() 方法运行一些库代码,在成功回调中,它将数字和布尔值设置为不同的值(见下面的 A 行和 B 行)。
问题:我的组件仅在存在 A 行时重新呈现自身。在这种情况下,初始化完成后,会出现“就绪”文本,并出现按钮。如果我删除 B 行,“就绪”文本仍然会出现。但是如果我删除 A 行(并保留 B 行),按钮永远不会呈现。我检查了一百多次,一切都正确导入,我打开了装饰器支持。我无法想象为什么观察一个数字可以触发重新渲染,但观察一个布尔值却不能。恐怕我在这里遗漏了一些非常明显的东西。有什么想法吗?
相关的简化代码如下:
// store/app.store.ts
export class AppStore {
@observable ready = false
@observable x = 5
initialize() {
// Takes a callback
ThirdPartyService.init(() => {
this.ready = true
this.x = 10
})
}
}
// context/stores.ts
const appStore = new AppStore()
const storesContext = React.createContext({
appStore
})
export const useStores = () => React.useContext(storesContext)
// App.tsx
const App = observer(() => {
const { appStore } = useStores()
useEffect(() => {
appStore.initialize()
}, [appStore])
return (
<div>
{ appStore.x === 10 && 'ready' } // <-- Line A
{ appStore.ready && <button>Go</button> } // <-- Line B
</div>
)
}
编辑:更多信息。我在App 组件的return 语句之前添加了一些日志记录语句。我还将button 条件重构为const。这可能会提供更多见解:
const button = appStore.ready ? <button>Go</button> : null
console.log('render', appStore.ready)
console.log('button', button)
return (
<div className="App">
<header className="App-header">{button}</header>
</div>
)
当appStore.ready 更新时,组件会重新渲染,但 DOM 不会更新。控制台显示'render' true 并按原样显示按钮的表示,但检查文档本身显示没有按钮。不过,不知何故,将条件从 appStore.ready 更改为 appStore.x === 10 确实会更新 DOM。
【问题讨论】:
-
代码看起来确实很正常。你能创建一个最小的复制品(例如作为 github 上的独立项目)吗?
-
实际上...我在
initialize()上没有看到@action装饰器 - 它只是从示例代码中省略了,还是在实际应用程序中实际上丢失了? -
@amakhrov 它在应用程序中丢失,但我尝试用
@action、@action.bound装饰initialize(),并尝试在ready和x内运行更新runInAction(),但不幸的是没有一个有所作为。我会尽快复制并在此处链接,谢谢。与此同时,我还更新了我的问题,提供了更多信息。
标签: javascript reactjs typescript mobx