如何在持久的 NextJS React Audio Player 组件中捕获 Mobx 可观察更新?
How to catch Mobx observable updates in persistent NextJS React Audio Player component?
我有一个服务器端呈现的音频播放器 React 应用程序。
使用 NextJS' custom _app.js,我有一个持久的 AudioPlayer 组件,每当 mobx 存储中 @observable playerData = {}
发生变化时,我想在其中调用一个内部 this.play(mp3url)
函数。
我已成功地在我的应用更新 playerData 中的其他组件上按需要点击按钮。
但是我无法在我的 AudioPlayer 组件中检测到这些更新,因此我可以设置它的状态并调用 this.play(mp3url)
开始播放音频。
pages/_app.js
import initializeStore from '../stores/stores';
export default class MyApp extends App {
static async getInitialProps(appContext) {
const mobxStore = initializeStore();
appContext.ctx.mobxStore = mobxStore;
const appProps = await App.getInitialProps(appContext);
return {
...appProps,
initialMobxState: mobxStore,
};
}
constructor(props) {
super(props);
this.mobxStore = props.initialMobxState;
}
render () {
const { Component, pageProps } = this.props
return (
<Provider {...this.mobxStore}>
<Component {...pageProps} />
{ this.mobxStore.playerStore.playerActive && <AudioPlayer /> }
</Provider>
)
}
}
components/AudioPlayer.js
import ReactPlayer from 'react-player'
import { inject, observer } from 'mobx-react'
@inject('playerStore')
@observer
class Player extends Component{
constructor(props) {
super(props)
this.state = {
url: null,
image: null
}
}
componentWillUpdate(nextProps) {
this.setState({
url: nextProps.playerStore.playerData.url,
image: nextProps.playerStore.playerData.image
}, () => { this.play(this.state.url) })
}
// ...Other react-player functions
render() {
<ReactPlayer
{/* ...required props... */}
/>
}
}
So how would one get this persistent audio player to detect changes in the
mobx observable to play audio urls?
截至目前,componentWillReceiveProps
、componentWillUpdate
或 componentDidUpdate
不会被调用。当我设置 @observable playerActive = true
时,componentDidMount
按预期准确调用一次
设法弄明白了。它是由 两个问题 引起的。
- 根据 Mobx 文档
The observer function / decorator can be used to turn ReactJS components into reactive components. It wraps the component's render function in mobx.autorun to make sure that any data that is used during the rendering of a component forces a re-rendering upon change. It is available through the separate mobx-react package.
store observable 需要在观察者组件的渲染函数中使用,以便组件对其更改做出反应。所以我将它们添加到 AudioPlayer 组件中,而不是从它自己的状态中获取它们。
- 我在
pages/_app.js
构造函数中遗漏了这一行关键代码,它可以在客户端正确初始化 mobx 存储。
this.mobxStore = isServer ? props.initialMobxState : initializeStore(props.initialMobxState)
现在 AudioPlayer 组件对 mobx observable 的每次更新做出反应,我能够在 componentWillUpdate
/componentDidUpdate
中处理任何进一步需要的逻辑
我有一个服务器端呈现的音频播放器 React 应用程序。
使用 NextJS' custom _app.js,我有一个持久的 AudioPlayer 组件,每当 mobx 存储中 @observable playerData = {}
发生变化时,我想在其中调用一个内部 this.play(mp3url)
函数。
我已成功地在我的应用更新 playerData 中的其他组件上按需要点击按钮。
但是我无法在我的 AudioPlayer 组件中检测到这些更新,因此我可以设置它的状态并调用 this.play(mp3url)
开始播放音频。
pages/_app.js
import initializeStore from '../stores/stores';
export default class MyApp extends App {
static async getInitialProps(appContext) {
const mobxStore = initializeStore();
appContext.ctx.mobxStore = mobxStore;
const appProps = await App.getInitialProps(appContext);
return {
...appProps,
initialMobxState: mobxStore,
};
}
constructor(props) {
super(props);
this.mobxStore = props.initialMobxState;
}
render () {
const { Component, pageProps } = this.props
return (
<Provider {...this.mobxStore}>
<Component {...pageProps} />
{ this.mobxStore.playerStore.playerActive && <AudioPlayer /> }
</Provider>
)
}
}
components/AudioPlayer.js
import ReactPlayer from 'react-player'
import { inject, observer } from 'mobx-react'
@inject('playerStore')
@observer
class Player extends Component{
constructor(props) {
super(props)
this.state = {
url: null,
image: null
}
}
componentWillUpdate(nextProps) {
this.setState({
url: nextProps.playerStore.playerData.url,
image: nextProps.playerStore.playerData.image
}, () => { this.play(this.state.url) })
}
// ...Other react-player functions
render() {
<ReactPlayer
{/* ...required props... */}
/>
}
}
So how would one get this persistent audio player to detect changes in the mobx observable to play audio urls?
截至目前,componentWillReceiveProps
、componentWillUpdate
或 componentDidUpdate
不会被调用。当我设置 @observable playerActive = true
componentDidMount
按预期准确调用一次
设法弄明白了。它是由 两个问题 引起的。
- 根据 Mobx 文档
The observer function / decorator can be used to turn ReactJS components into reactive components. It wraps the component's render function in mobx.autorun to make sure that any data that is used during the rendering of a component forces a re-rendering upon change. It is available through the separate mobx-react package.
store observable 需要在观察者组件的渲染函数中使用,以便组件对其更改做出反应。所以我将它们添加到 AudioPlayer 组件中,而不是从它自己的状态中获取它们。
- 我在
pages/_app.js
构造函数中遗漏了这一行关键代码,它可以在客户端正确初始化 mobx 存储。
this.mobxStore = isServer ? props.initialMobxState : initializeStore(props.initialMobxState)
现在 AudioPlayer 组件对 mobx observable 的每次更新做出反应,我能够在 componentWillUpdate
/componentDidUpdate