Reactçµ±å
äœ¿çšæ¹æ³
import { observer } from "mobx-react-lite" // Or "mobx-react".
const MyComponent = observer(props => ReactElement)
MobXã¯Reactãšã¯ç¬ç«ããŠåäœããŸãããæãäžè¬çã«ã¯äžç·ã«äœ¿çšãããŸããMobXã®æŠèŠã§ã¯ããã®çµ±åã®æãéèŠãªéšåã§ãããReactã³ã³ããŒãã³ãã«ã©ããã§ããobserver
HOCãæ¢ã«èŠãŠããŸããã
observer
ã¯ãã€ã³ã¹ããŒã«æã«éžæããåå¥ã®Reactãã€ã³ãã£ã³ã°ããã±ãŒãžã«ãã£ãŠæäŸãããŸãããã®äŸã§ã¯ããã軜éãªmobx-react-lite
ããã±ãŒãžã䜿çšããŸãã
import React from "react"
import ReactDOM from "react-dom"
import { makeAutoObservable } from "mobx"
import { observer } from "mobx-react-lite"
class Timer {
secondsPassed = 0
constructor() {
makeAutoObservable(this)
}
increaseTimer() {
this.secondsPassed += 1
}
}
const myTimer = new Timer()
// A function component wrapped with `observer` will react
// to any future change in an observable it used before.
const TimerView = observer(({ timer }) => <span>Seconds passed: {timer.secondsPassed}</span>)
ReactDOM.render(<TimerView timer={myTimer} />, document.body)
setInterval(() => {
myTimer.increaseTimer()
}, 1000)
ãã³ã: äžèšã®äŸã¯ãCodeSandboxã§èªåã§è©Šãããšãã§ããŸãã
observer
HOCã¯ãã¬ã³ããªã³ã°äžã«äœ¿çšããããã¹ãŠã®ãªãã¶ãŒããã«ã«Reactã³ã³ããŒãã³ããèªåçã«ãµãã¹ã¯ã©ã€ãããŸãããã®çµæãé¢é£ãããªãã¶ãŒããã«ã倿Žããããšãã³ã³ããŒãã³ãã¯èªåçã«åã¬ã³ããªã³ã°ãããŸãããŸããé¢é£ã®ãªã倿Žããªãå Žåã¯ãã³ã³ããŒãã³ããåã¬ã³ããªã³ã°ãããªãããã«ããŸãããã®ãããã³ã³ããŒãã³ãããã¢ã¯ã»ã¹ã§ãããªãã¶ãŒããã«ã§ããå®éã«ã¯èªã¿åãããŠããªããã®ã¯ãåã¬ã³ããªã³ã°ã®åå ã«ã¯ãªããŸããã
å®éãããã«ããMobXã¢ããªã±ãŒã·ã§ã³ã¯ããã«æé©åãããéåžžã¯éå°ãªã¬ã³ããªã³ã°ãé²ãããã®è¿œå ã³ãŒãã¯å¿ èŠãããŸããã
observer
ãæ©èœããã«ã¯ããªãã¶ãŒããã«ãã³ã³ããŒãã³ãã«ã©ã®ããã«æž¡ããããã¯é¢ä¿ãããŸãããèªã¿åãããããšã ãã§ãããªãã¶ãŒããã«ãæ·±ãèªã¿åã£ãŠãåé¡ãããŸãããtodos[0].author.displayName
ã®ãããªè€éãªåŒãããã«åäœããŸããããã«ããããµãã¹ã¯ãªãã·ã§ã³ã¡ã«ããºã ã¯ãããŒã¿äŸåé¢ä¿ãæç€ºçã«å®£èšããããäºåã«èšç®ããå¿
èŠãããïŒäŸïŒã»ã¬ã¯ã¿ãŒïŒä»ã®ãã¬ãŒã ã¯ãŒã¯ãšæ¯èŒããŠãã¯ããã«æ£ç¢ºã§å¹ççã«ãªããŸãã
ããŒã«ã«ç¶æ ãšå€éšç¶æ
ç¶æ
ã®æ§ææ¹æ³ã«ã¯æè»æ§ãããã(æè¡çã«ã¯)ã©ã®ãªãã¶ãŒããã«ãèªã¿åãã®ãããŸãã¯ãªãã¶ãŒããã«ã¯ã©ãããæ¥ãã®ãã¯é¢ä¿ãããŸããã以äžã®äŸã§ã¯ãobserver
ã§ã©ãããããã³ã³ããŒãã³ãã§ãå€éšãšããŒã«ã«ã®ãªãã¶ãŒããã«ç¶æ
ã䜿çšããããŸããŸãªãã¿ãŒã³ã瀺ããŠããŸãã
observer
ã³ã³ããŒãã³ãã§ã®å€éšç¶æ
ã®äœ¿çš
ãªãã¶ãŒããã«ã¯propsãšããŠã³ã³ããŒãã³ãã«æž¡ãããšãã§ããŸãïŒäžèšã®äŸã®ããã«ïŒã
import { observer } from "mobx-react-lite"
const myTimer = new Timer() // See the Timer definition above.
const TimerView = observer(({ timer }) => <span>Seconds passed: {timer.secondsPassed}</span>)
// Pass myTimer as a prop.
ReactDOM.render(<TimerView timer={myTimer} />, document.body)
ãªãã¶ãŒããã«ãžã®åç §ãååŸããæ¹æ³ã«é¢ä¿ãªããå€éšã¹ã³ãŒãïŒã€ã³ããŒããªã©ïŒããçŽæ¥ãªãã¶ãŒããã«ã䜿çšã§ããŸãã
const myTimer = new Timer() // See the Timer definition above.
// No props, `myTimer` is directly consumed from the closure.
const TimerView = observer(() => <span>Seconds passed: {myTimer.secondsPassed}</span>)
ReactDOM.render(<TimerView />, document.body)
ãªãã¶ãŒããã«ãçŽæ¥äœ¿çšããã®ã¯éåžžã«å¹æçã§ãããéåžžã¯ã¢ãžã¥ãŒã«ç¶æ ãå°å ¥ãããããããã®ãã¿ãŒã³ã¯ãŠããããã¹ããè€éã«ããå¯èœæ§ããããŸãã代ããã«ãReactã³ã³ããã¹ãã®äœ¿çšããå§ãããŸãã
Reactã³ã³ããã¹ãã¯ããªãã¶ãŒããã«ããµãããªãŒå šäœãšå ±æããããã®åªããã¡ã«ããºã ã§ãã
import {observer} from 'mobx-react-lite'
import {createContext, useContext} from "react"
const TimerContext = createContext<Timer>()
const TimerView = observer(() => {
// Grab the timer from the context.
const timer = useContext(TimerContext) // See the Timer definition above.
return (
<span>Seconds passed: {timer.secondsPassed}</span>
)
})
ReactDOM.render(
<TimerContext.Provider value={new Timer()}>
<TimerView />
</TimerContext.Provider>,
document.body
)
Provider
ã®value
ãå¥ã®ãã®ã«çœ®ãæããããšã¯ãå§ãããŸãããMobXã䜿çšãããšãå
±æããããªãã¶ãŒããã«èªäœãæŽæ°ã§ããããããã®ãããªå¿
èŠã¯ãããŸããã
observer
ã³ã³ããŒãã³ãã§ã®ããŒã«ã«ãªãã¶ãŒããã«ç¶æ
ã®äœ¿çš
observer
ã§äœ¿çšããããªãã¶ãŒããã«ã¯ã©ãããã§ãååŸã§ãããããããŒã«ã«ç¶æ
ã«ããããšãã§ããŸããããã§ããããŸããŸãªãªãã·ã§ã³ãå©çšå¯èœã§ãã
ããŒã«ã«ãªãã¶ãŒããã«ç¶æ
ã䜿çšããæãç°¡åãªæ¹æ³ã¯ãuseState
ã䜿çšããŠãªãã¶ãŒããã«ã¯ã©ã¹ãžã®åç
§ãä¿åããããšã§ããéåžžã¯åç
§ã眮ãæããããªãã®ã§ãuseState
ã«ãã£ãŠè¿ãããæŽæ°é¢æ°ã¯å®å
šã«ç¡èŠããŸãã
import { observer } from "mobx-react-lite"
import { useState } from "react"
const TimerView = observer(() => {
const [timer] = useState(() => new Timer()) // See the Timer definition above.
return <span>Seconds passed: {timer.secondsPassed}</span>
})
ReactDOM.render(<TimerView />, document.body)
å
ã®äŸã®ããã«ã¿ã€ããŒãèªåçã«æŽæ°ãããå Žåã¯ãéåžžã®Reactã®æ¹æ³ã§useEffect
ã䜿çšã§ããŸãã
useEffect(() => {
const handle = setInterval(() => {
timer.increaseTimer()
}, 1000)
return () => {
clearInterval(handle)
}
}, [timer])
åè¿°ã®ããã«ãã¯ã©ã¹ã䜿çšãã代ããã«ããªãã¶ãŒããã«ãªããžã§ã¯ããçŽæ¥äœæã§ããŸããobservableãå©çšã§ããŸãã
import { observer } from "mobx-react-lite"
import { observable } from "mobx"
import { useState } from "react"
const TimerView = observer(() => {
const [timer] = useState(() =>
observable({
secondsPassed: 0,
increaseTimer() {
this.secondsPassed++
}
})
)
return <span>Seconds passed: {timer.secondsPassed}</span>
})
ReactDOM.render(<TimerView />, document.body)
const [store] = useState(() => observable({ /* something */}))
ã®çµã¿åããã¯éåžžã«äžè¬çã§ãããã®ãã¿ãŒã³ãç°¡çŽ åããããã«ãuseLocalObservable
ããã¯ãmobx-react-lite
ããã±ãŒãžããå
¬éãããŠããã以åã®äŸã次ã®ããã«ç°¡çŽ åã§ããŸãã
import { observer, useLocalObservable } from "mobx-react-lite"
const TimerView = observer(() => {
const timer = useLocalObservable(() => ({
secondsPassed: 0,
increaseTimer() {
this.secondsPassed++
}
}))
return <span>Seconds passed: {timer.secondsPassed}</span>
})
ReactDOM.render(<TimerView />, document.body)
ããŒã«ã«ãªãã¶ãŒããã«ç¶æ ã¯äžèŠãªå ŽåããããŸã
äžè¬çã«ãããŒã«ã«ã³ã³ããŒãã³ãã®ç¶æ ã«MobXãªãã¶ãŒããã«ãããã«é Œããªãããšããå§ãããŸããããã¯çè«çã«Reactã®Suspenseã¡ã«ããºã ã®äžéšã®æ©èœãå¶éããå¯èœæ§ãããããã§ããçµéšåãšããŠãç¶æ ãã³ã³ããŒãã³ãïŒåã³ã³ããŒãã³ããå«ãïŒéã§å ±æããããã¡ã€ã³ããŒã¿ïŒã¿ã¹ã¯ã¢ã€ãã ããŠãŒã¶ãŒãäºçŽãªã©ïŒããã£ããã£ããå Žåã¯ãMobXãªãã¶ãŒããã«ã䜿çšããŸãã
èªã¿èŸŒã¿ç¶æ
ãéžæãªã©ãUIç¶æ
ã®ã¿ããã£ããã£ããç¶æ
ã¯ãuseState
ããã¯ã®æ¹ãé©ããŠããå ŽåããããŸããããã«ãããå°æ¥Reactã®Suspenseæ©èœã掻çšã§ããŸãã
Reactã³ã³ããŒãã³ãå
ã§ãªãã¶ãŒããã«ã䜿çšãããšã1ïŒæ·±ãã2ïŒèšç®å€ãæã€ã3ïŒä»ã®observer
ã³ã³ããŒãã³ããšå
±æãããŠããå Žåã«äŸ¡å€ã远å ãããŸãã
observer
ã³ã³ããŒãã³ãå
ã§åžžã«ãªãã¶ãŒããã«ãèªã¿åã
ãã€observer
ãé©çšãããçåã«æããããããããŸãããçµéšåã¯æ¬¡ã®ãšããã§ãããªãã¶ãŒããã«ããŒã¿ãèªã¿åããã¹ãŠã®ã³ã³ããŒãã³ãã«observer
ãé©çšããŸãã
observer
ã¯ããã³ã¬ãŒãããŠããã³ã³ããŒãã³ãã®ã¿ã匷åããããã«ãã£ãŠåŒã³åºãããã³ã³ããŒãã³ãã¯åŒ·åããŸããããã®ãããéåžžã¯ãã¹ãŠã®ã³ã³ããŒãã³ããobserver
ã§ã©ããããå¿
èŠããããŸããå¿é
ããå¿
èŠã¯ãããŸãããããã¯éå¹çã§ã¯ãããŸãããéã«ãããå€ãã®observer
ã³ã³ããŒãã³ãã䜿çšãããšãæŽæ°ããã詳现ã«ãªããããã¬ã³ããªã³ã°ãããå¹ççã«ãªããŸãã
ãã³ãïŒãªããžã§ã¯ãããã®å€ã¯ã§ããã ãé ãååŸãã
ãªããžã§ã¯ãåç
§ãã§ããã ãé·ãæž¡ãããããã®ããããã£ãDOM/äœã¬ãã«ã³ã³ããŒãã³ãã«ã¬ã³ããªã³ã°ããobserver
ããŒã¹ã®ã³ã³ããŒãã³ãå
ã§èªã¿åãå Žåãobserver
ã¯æé©ã«æ©èœããŸããèšãæããã°ãobserver
ã¯ããªããžã§ã¯ãããå€ããéåç
§ããããšããäºå®ã«åå¿ããŸãã
äžèšã®äŸã§ã¯ã.secondsPassed
ãobserver
ã³ã³ããŒãã³ãå
ã§ã§ã¯ãªãå€åŽã§èªã¿åãããããã远跡ããããTimerView
ã³ã³ããŒãã³ãã¯ã次ã®ããã«å®çŸ©ãããŠããå Žåãå°æ¥ã®å€æŽã«ã¯åå¿ããŸããã
const TimerView = observer(({ secondsPassed }) => <span>Seconds passed: {secondsPassed}</span>)
React.render(<TimerView secondsPassed={myTimer.secondsPassed} />, document.body)
ããã¯ãreact-redux
ãªã©ã®ä»ã®ã©ã€ãã©ãªãšã¯ç°ãªãèãæ¹ã§ããreact-redux
ã§ã¯ãã¡ã¢åããã广çã«æŽ»çšããããã«ãæ©æã«éåç
§ããŠããªããã£ããæž¡ãããšãæšå¥šãããããã§ããåé¡ãå®å
šã«æç¢ºã§ãªãå Žåã¯ããªã¢ã¯ãã£ããã£ã®çè§£ã»ã¯ã·ã§ã³ã確èªããŠãã ããã
observer
ã§ã¯ãªãã³ã³ããŒãã³ãã«ãªãã¶ãŒããã«ãæž¡ããªã
observer
ã§ã©ãããããã³ã³ããŒãã³ãã¯ãã³ã³ããŒãã³ãã®ç¬èªã®ã¬ã³ããªã³ã°äžã«äœ¿çšããããªãã¶ãŒããã«ã«ã®ã¿ãµãã¹ã¯ã©ã€ãããŸãããã®ããããªãã¶ãŒããã«ãªããžã§ã¯ã/é
å/ããããåã³ã³ããŒãã³ãã«æž¡ãããå Žåãããããobserver
ã§ã©ããããå¿
èŠããããŸããããã¯ãã³ãŒã«ããã¯ããŒã¹ã®ã³ã³ããŒãã³ãã«ãåœãŠã¯ãŸããŸãã
ãªãã¶ãŒãã§ã¯ãªãã³ã³ããŒãã³ãïŒãµãŒãããŒãã£ã®ã³ã³ããŒãã³ãã®å Žåãããã®ã³ã³ããŒãã³ããMobXã«äŸåãããããªãå Žåãªã©ïŒã«ãªãã¶ãŒããã«ãæž¡ãã«ã¯ããªãã¶ãŒããã«ããã¬ãŒã³ãªJavaScriptã®å€ãŸãã¯æ§é ã«å€æããå¿ èŠããããŸãã
äžèšã詳ãã説æããããã«ããªãã¶ãŒããã«ãªtodo
ãªããžã§ã¯ããTodoView
ã³ã³ããŒãã³ãïŒãªãã¶ãŒãïŒããããŠå/å€ãããã³ã°ãåãåãããªãã¶ãŒãã§ã¯ãªãæ¶ç©ºã®GridRow
ã³ã³ããŒãã³ãã®äŸãèããŠã¿ãŸãããã
class Todo {
title = "test"
done = true
constructor() {
makeAutoObservable(this)
}
}
const TodoView = observer(({ todo }: { todo: Todo }) =>
// WRONG: GridRow won't pick up changes in todo.title / todo.done
// since it isn't an observer.
return <GridRow data={todo} />
// CORRECT: let `TodoView` detect relevant changes in `todo`,
// and pass plain data down.
return <GridRow data={{
title: todo.title,
done: todo.done
}} />
// CORRECT: using `toJS` works as well, but being explicit is typically better.
return <GridRow data={toJS(todo)} />
)
<Observer>
ãå¿
èŠãšããå ŽåããããŸãã
ã³ãŒã«ããã¯ã³ã³ããŒãã³ãã¯GridRow
ãonRender
ã³ãŒã«ããã¯ãåãåãå ŽåãèããŠã¿ãŸããããonRender
ã¯TodoView
ã®ã¬ã³ããªã³ã°ã§ã¯ãªãGridRow
ã®ã¬ã³ããªã³ã°ãµã€ã¯ã«ã®äžéšã§ããããïŒæ§æäžã¯TodoView
ã«åºçŸãããã®ã®ïŒãã³ãŒã«ããã¯ã³ã³ããŒãã³ããobserver
ã³ã³ããŒãã³ãã䜿çšããŠããããšã確èªããå¿
èŠããããŸãããŸãã¯ã<Observer />
ã䜿çšããŠã€ã³ã©ã€ã³ã®å¿åãªãã¶ãŒããäœæããããšãã§ããŸãã
const TodoView = observer(({ todo }: { todo: Todo }) => {
// WRONG: GridRow.onRender won't pick up changes in todo.title / todo.done
// since it isn't an observer.
return <GridRow onRender={() => <td>{todo.title}</td>} />
// CORRECT: wrap the callback rendering in Observer to be able to detect changes.
return <GridRow onRender={() => <Observer>{() => <td>{todo.title}</td>}</Observer>} />
})
ãã³ã
ãµãŒããŒãµã€ãã¬ã³ããªã³ã°ïŒSSRïŒ
ãµãŒããŒãµã€ãã¬ã³ããªã³ã°ã®ã³ã³ããã¹ãã§observer
ã䜿çšããå Žåã¯ãenableStaticRendering(true)
ãåŒã³åºããŠãobserver
ã䜿çšãããŠãããªãã¶ãŒããã«ã賌èªãããGCã®åé¡ãçºçããªãããã«ããŠãã ãããæ³šèšïŒmobx-react 察 mobx-react-lite
ãã®ããã¥ã¡ã³ãã§ã¯ãããã©ã«ããšããŠmobx-react-lite
ã䜿çšããŠããŸããmobx-reactã¯ãã®äžäœçã§ãããå
éšã§mobx-react-lite
ã䜿çšããŠããŸããã°ãªãŒã³ãã£ãŒã«ããããžã§ã¯ãã§ã¯éåžžäžèŠãšãªã£ãããã€ãã®è¿œå æ©èœãæäŸããŠããŸããmobx-reactã«ãã£ãŠæäŸãããè¿œå æ©èœã¯æ¬¡ã®ãšããã§ãã
- Reactã¯ã©ã¹ã³ã³ããŒãã³ãã®ãµããŒãã
Provider
ãšinject
ãMobXç¬èªã®React.createContextã®å身ã§ããããã¯ãå¿ èŠãããŸããã- ãªãã¶ãŒããã«åºæã®
propTypes
ã
mobx-react
ã¯ã颿°ã³ã³ããŒãã³ãã®ãµããŒããå«ããmobx-react-lite
ãå®å
šã«åããã±ãŒãžåããŠåãšã¯ã¹ããŒãããããšã«æ³šæããŠãã ãããmobx-react
ã䜿çšããå Žåã¯ãmobx-react-lite
ãäŸåé¢ä¿ãšããŠè¿œå ããããã©ãããã§ãã€ã³ããŒãããå¿
èŠã¯ãããŸããã
泚èšïŒobserver
ãŸãã¯React.memo
ïŒ
observer
ã¯èªåçã«memo
ãé©çšãããããobserver
ã³ã³ããŒãã³ããmemo
ã§ã©ããããå¿
èŠã¯ãããŸãããããããã¹ã®å
éšïŒæ·±ãïŒã®å€æŽã¯ãé¢é£ããå Žåã¯observer
ã«ãã£ãŠæŸããããããmemo
ã¯observer
ã³ã³ããŒãã³ãã«å®å
šã«é©çšã§ããŸãããã³ãïŒã¯ã©ã¹ããŒã¹ã®Reactã³ã³ããŒãã³ãã®observer
äžèšã®ããã«ãã¯ã©ã¹ããŒã¹ã®ã³ã³ããŒãã³ãã¯mobx-react
ã§ã®ã¿ãµããŒããããmobx-react-lite
ã§ã¯ãµããŒããããŸãããç°¡åã«èšããšã颿°ã³ã³ããŒãã³ããã©ããããã®ãšåãããã«ãã¯ã©ã¹ããŒã¹ã®ã³ã³ããŒãã³ããobserver
ã§ã©ããã§ããŸãã
import React from "React"
const TimerView = observer(
class TimerView extends React.Component {
render() {
const { timer } = this.props
return <span>Seconds passed: {timer.secondsPassed} </span>
}
}
)
詳现ã«ã€ããŠã¯ãmobx-reactã®ããã¥ã¡ã³ããåç §ããŠãã ããã
ãã³ãïŒReact DevToolsã§ã®ã³ã³ããŒãã³ãåã®è¡šç€º
React DevToolsã¯ãã³ã³ããŒãã³ãã®è¡šç€ºåæ å ±ã䜿çšããŠãã³ã³ããŒãã³ãéå±€ãé©åã«è¡šç€ºããŸããæ¬¡ã䜿çšããå Žå
export const MyComponent = observer(props => <div>hi</div>)
DevToolsã«ã¯è¡šç€ºåã衚瀺ãããŸããã
ãããä¿®æ£ããã«ã¯ãæ¬¡ã®æ¹æ³ã䜿çšã§ããŸãã
ã¢ããŒé¢æ°ã§ã¯ãªãååä»ãã®
function
ã䜿çšããŸããmobx-react
ã¯é¢æ°åããã³ã³ããŒãã³ãåãæšæž¬ããŸããexport const MyComponent = observer(function MyComponent(props) { return <div>hi</div> })
ãã©ã³ã¹ãã€ã©ïŒBabelãTypeScriptãªã©ïŒã¯ã倿°åããã³ã³ããŒãã³ãåãæšæž¬ããŸãã
const _MyComponent = props => <div>hi</div> export const MyComponent = observer(_MyComponent)
ããã©ã«ããšã¯ã¹ããŒãã䜿çšããŠã倿°åããååºŠæšæž¬ããŸãã
const MyComponent = props => <div>hi</div> export default observer(MyComponent)
[å£ããŠããŸã]
displayName
ãæç€ºçã«èšå®ããŸããexport const MyComponent = observer(props => <div>hi</div>) MyComponent.displayName = "MyComponent"
ããã¯ãå·çæç¹ã§ã®React 16ã§ã¯å£ããŠããŸããmobx-react
observer
ã¯React.memoã䜿çšããŠããããã®ãã°ãçºçããŸããhttps://github.com/facebook/react/issues/18026ããããReact 17ã§ä¿®æ£ãããäºå®ã§ãã
ããã§ã³ã³ããŒãã³ãåã衚瀺ãããããã«ãªããŸããã
{ð} ãã³ãïŒobserver
ãä»ã®é«éã³ã³ããŒãã³ããšçµã¿åãããå Žåã¯ãæåã«observer
ãé©çšããŸã
observer
ãä»ã®ãã³ã¬ãŒã¿ãŸãã¯é«éã³ã³ããŒãã³ããšçµã¿åãããå¿
èŠãããå Žåã¯ãobserver
ãæãå
åŽã®ïŒæåã«é©çšãããïŒãã³ã¬ãŒã¿ã§ããããšã確èªããŠãã ãããããã§ãªããšããŸã£ããæ©èœããªãå¯èœæ§ããããŸãã
{ð} ãã³ãïŒããããã¹ããã®computedã®å°åº
å Žåã«ãã£ãŠã¯ãããŒã«ã«ãªãã¶ãŒããã«ã®computedå€ããã³ã³ããŒãã³ããåãåãããããã¹ã®ããã€ãã«ãã£ãŠäŸåããå ŽåããããŸããããããReactã³ã³ããŒãã³ããåãåãããããã¹ã®ã»ããèªäœã¯ãªãã¶ãŒããã«ã§ã¯ãªããããããããã¹ã®å€æŽã¯computedå€ã«åæ ãããŸãããææ°ã®ããŒã¿ããcomputedå€ãé©åã«å°åºããã«ã¯ãããŒã«ã«ãªãã¶ãŒããã«ã®ç¶æ ãæåã§æŽæ°ããå¿ èŠããããŸããimport { observer, useLocalObservable } from "mobx-react-lite"
import { useEffect } from "react"
const TimerView = observer(({ offset = 0 }) => {
const timer = useLocalObservable(() => ({
offset, // The initial offset value
secondsPassed: 0,
increaseTimer() {
this.secondsPassed++
},
get offsetTime() {
return this.secondsPassed - this.offset // Not 'offset' from 'props'!
}
}))
useEffect(() => {
// Sync the offset from 'props' into the observable 'timer'
timer.offset = offset
}, [offset])
// Effect to set up a timer, only for demo purposes.
useEffect(() => {
const handle = setInterval(timer.increaseTimer, 1000)
return () => {
clearInterval(handle)
}
}, [])
return <span>Seconds passed: {timer.offsetTime}</span>
})
ReactDOM.render(<TimerView />, document.body)
å®éã«ã¯ãreturn <span>Seconds passed: {timer.secondsPassed - offset}</span>
ã¯ãããå¹çãäœããã®ã®ãã¯ããã«åçŽãªè§£æ±ºçã§ããããããã®ãã¿ãŒã³ã¯ãã£ãã«å¿
èŠãããŸããã
{ð} ãã³ãïŒuseEffectãšãªãã¶ãŒããã«
useEffect
ã¯ãçºçããå¿
èŠãããå¯äœçšãèšå®ããReactã³ã³ããŒãã³ãã®ã©ã€ããµã€ã¯ã«ã«ãã€ã³ãããããã«äœ¿çšã§ããŸããuseEffect
ã䜿çšããã«ã¯ãäŸåé¢ä¿ãæå®ããå¿
èŠããããŸããMobXã§ã¯ãMobXã«ã¯ãã§ã«å¹æã®äŸåé¢ä¿ãèªåçã«æ±ºå®ããæ¹æ³ïŒautorun
ïŒããããããããã¯å®éã«ã¯å¿
èŠãããŸãããautorun
ãšuseEffect
ã䜿çšããŠã³ã³ããŒãã³ãã®ã©ã€ããµã€ã¯ã«ã«çµåããããšã¯ã幞ãã«ãç°¡åã§ãã
import { observer, useLocalObservable, useAsObservableSource } from "mobx-react-lite"
import { useState } from "react"
const TimerView = observer(() => {
const timer = useLocalObservable(() => ({
secondsPassed: 0,
increaseTimer() {
this.secondsPassed++
}
}))
// Effect that triggers upon observable changes.
useEffect(
() =>
autorun(() => {
if (timer.secondsPassed > 60) alert("Still there. It's a minute already?!!")
}),
[]
)
// Effect to set up a timer, only for demo purposes.
useEffect(() => {
const handle = setInterval(timer.increaseTimer, 1000)
return () => {
clearInterval(handle)
}
}, [])
return <span>Seconds passed: {timer.secondsPassed}</span>
})
ReactDOM.render(<TimerView />, document.body)
广颿°ããautorun
ã«ãã£ãŠäœæããããã£ã¹ããŒã¶ãè¿ãããšãéèŠã§ããããã¯ãã³ã³ããŒãã³ããã¢ã³ããŠã³ãããããšãã«autorun
ã確å®ã«ã¯ãªãŒã³ã¢ãããããããã«ããããã§ãã
ãªãã¶ãŒããã«ã§ã¯ãªãå€ãautorunã®åå®è¡ãããªã¬ãŒããå¿
èŠãããå Žåãé€ããäŸåé¢ä¿é
åã¯é垞空ã®ãŸãŸã«ããããšãã§ããŸãããã®å Žåãããã«è¿œå ããå¿
èŠããããŸãããªã³ã¿ãŒãæºè¶³ãããããã«ãïŒäžèšã®äŸã§ã¯ïŒtimer
ãäŸåé¢ä¿ãšããŠå®çŸ©ã§ããŸããåç
§ã¯å®éã«ã¯æ±ºããŠå€æŽãããªããããããã¯å®å
šã§ãããããã«åœ±é¿ã¯ãããŸããã
广ãããªã¬ãŒãããªãã¶ãŒããã«ãæç€ºçã«å®çŸ©ããå Žåã¯ãautorun
ã®ä»£ããã«reaction
ã䜿çšããŸãããã以å€ã¯ãã¿ãŒã³ã¯åããŸãŸã§ãã
Reactã³ã³ããŒãã³ããããã«æé©åããã«ã¯ïŒ
Reactã®æé©å {ð}ã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
ãã©ãã«ã·ã¥ãŒãã£ã³ã°
ãã«ãïŒã³ã³ããŒãã³ããåã¬ã³ããªã³ã°ãããŸããâŠ
observer
ãå¿ããªãããã«ããŠãã ããïŒã¯ãããããæãäžè¬çãªééãã§ãïŒã- åå¿ãããããšããŠãããã®ãå®éã«ãªãã¶ãŒããã«ã§ããããšã確èªããŠãã ãããå¿
èŠã«å¿ããŠã
isObservable
ãisObservableProp
ãªã©ã®ãŠãŒãã£ãªãã£ã䜿çšããŠãå®è¡æã«ããã確èªããŸãã - ãã©ãŠã¶ã®ã³ã³ãœãŒã«ãã°ã§èŠåããšã©ãŒããªãã確èªããŠãã ããã
- 远跡ã®ä»çµã¿ãå šäœçã«çè§£ããŠããããšã確èªããŠãã ããããªã¢ã¯ãã£ããã£ã®çè§£ã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
- äžèšã§èª¬æãããŠããäžè¬çãªèœãšã穎ãèªãã§ãã ããã
- èšå®MobXã¯ãã¡ã«ããºã ã®äžå¥å šãªäœ¿çšã«ã€ããŠèŠåããã³ã³ãœãŒã«ãã°ã確èªããŸãã
- ãã¬ãŒã¹ã䜿çšããŠãæ£ãããã®ã賌èªããŠããããšã確èªããããspy/mobx-logããã±ãŒãžã䜿çšããŠMobXãäžè¬çã«äœãããŠãããã確èªããŸãã