一个关于 MobX 的疑问,为什么没有触发重新渲染?

2021-04-22 13:56:41 +08:00
 O3Q

在学习和使用 MobX 的时候遇到了一点问题:函数组件中可以正常触发组件重渲染,但是在相同行为的类组件中无法触发重渲染。 请问大神们这是为何?

依赖版本:

mobx: 6.2.0

mobx-react: 7.1.0

react: 16.8.6

react-dom: 16.8.6


可复现的代码:

import React from "react"
import ReactDOM from "react-dom"
import {makeAutoObservable} from "mobx";
import { observer } from "mobx-react"

class Timer {
    secondsPassed = 0

    constructor() {
        makeAutoObservable(this)
    }

    increase() {
        this.secondsPassed += 1
    }

    reset() {
        this.secondsPassed = 0
    }
}

const myTimer = new Timer()

const TimerView = observer((props) => (
    <button onClick={() => props.timer.increase()}>Seconds passed: {props.timer.secondsPassed}</button>
))


const Demo = observer(class Demo extends React.Component {
    public render = () => {
        return <button onClick={() => this.props.timer.increase()}>Seconds passed: {this.props.timer.secondsPassed}</button>
    }
})

ReactDOM.render(<>
    <Demo timer={myTimer} />
    <TimerView timer={myTimer} />
</>, document.body)
1457 次点击
所在节点    问与答
8 条回复
JK9993
2021-04-22 14:27:03 +08:00
请使用 state
JK9993
2021-04-22 14:28:08 +08:00
看错了,抱歉
lblblong
2021-04-22 14:51:37 +08:00
在类上使用是用装饰器,你这...

```typescript
@observer
class Demo extends React.Component {
...

```
SilencerL
2021-04-22 15:01:23 +08:00
@lblblong #3
虽然我不知道为啥楼主在类组件里面不重新渲染
但是目前来看装饰器不就是个语法糖……实际上用装饰器和 observer(component) 是一样的效果吧
lblblong
2021-04-22 15:50:31 +08:00
@SilencerL 好像是这样的,见笑了

我仔细看了下,楼主可能是类方法写错了,不能这么定义类方法吧
public render = () => {..}
改成 render(){} 或者 const render = () => {} 应该就可以了
ytxbnahn
2021-04-22 16:03:27 +08:00
```
const Demo = observer(
class Demo extends React.Component {
render() {
return (
<button onClick={() => this.props.timer.increase()}>
Seconds passed: {this.props.timer.secondsPassed}
</button>
);
}
}
);
```
JK9993
2021-04-22 16:40:38 +08:00
用 `observer` 包装 Class Component 的时候,它会使用 `makeClassComponentObserver` 方法。该方法会修改组件的 [`render` 方法]( https://github.com/mobxjs/mobx-react/blob/baa737e4faf458e3f4c89edebacfb8774b64353d/src/observerClass.ts#L55),这样才能收集到依赖。
而当你使用箭头函数的时候,如果你使用 `bebel` 或者其他编译器向低版本转化的话,箭头函数就会变成在构造函数中赋值的形式。
这个时候 `makeClassComponentObserver` 取到的该组件的 `render` 属性为 undefined,这样就会收集不到依赖,因此无法更新。
O3Q
2021-04-22 16:55:12 +08:00
@lblblong
@ytxbnahn
感谢二位的指点~

@JK9993
非常感谢这位朋友从源码 /底层的层面解答了问题~非常有帮助,感恩 2021 !

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/772440

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX