使用 React 和 Web Audio 进行状态管理
State Management with React and Web Audio
我正在尝试使用 Web Audio API 和 React 编写基于模块的音乐应用程序。
到目前为止,我一直在创建 Web 音频节点,例如过滤器、振荡器等,同时创建 React 组件:
class Filter extends React.Component {
constructor(props) {
super(props);
const filter = props.context.createBiquadFilter();
this.state = { filter };
}
...
稍后,这意味着可以将过滤器作为组件状态的一部分进行更改:
frequencyChange(event) {
...
this.state.filter.frequency.setValueAtTime(range.value, context.currentTime);
}
并在渲染方法中:
<input type="range" className="slider" min={20} max={20000}
onChange={event => this.frequencyChange(event)}/>
但是,当谈到将过滤器链接在一起时,我需要能够 disconnect()
我从该组件的父 class 创建的网络音频过滤器节点,并且 connect()
它到一个新的目的地。
假设父组件称为 EffectsBox
,旨在呈现任意效果列表,如 Filter
。
它应该如何呈现所有这些组件,并允许它们公开一些常见的 API 以将音频链接在一起?
这些效果的状态(即网络音频组件)应该存储在哪里?
下面是一些示例代码,希望能使我的问题更清楚:
class EffectsBox extends React.Component {
...
addNewEffect(effect) {
// disconnect() the previous effect and connect() it to a new one
}
render() {
// Maybe some kind of "map" here between effects and react components?
return <div>{ this.state.effects }</div>
}
N.B。 – 我读过 React 的 refs
API,但它似乎不适合与任意数量的子 classes 一起使用 – 很高兴以其他方式展示!
React 不喜欢在不使用 setState
的情况下编辑组件状态中的值。我会避免将整个音频节点置于状态,甚至根本不置于组件中。
我曾经尝试在构造函数中将音频节点添加为 class 的一部分,这样我就可以像 this.filter
一样访问内容。然后我不得不 use refs everywhere 并将音频上下文传递给 everything 以访问连接节点和设置值所需的方法。它发出了我想要的声音,但我不喜欢我的文件如此紧密耦合和冗长。
我重构了一切。现在有一个文件使用管理所有音频节点的音频上下文。它公开了一些方法,我可以根据需要使用它来更新值。我还有一个字符串名称到节点的映射,所以我设置的值是这样的:setValue('filter', 'frequency', newValue)
。有少数情况需要单独处理(即失真曲线),但总体上对我来说更容易阅读。这种抽象还意味着您的音频节点对组件层次结构的变化不敏感。
这是我推荐的。将你的音频节点从你的 React classes 中拉出来。管理管理节点的代码要简单得多。
我正在尝试使用 Web Audio API 和 React 编写基于模块的音乐应用程序。
到目前为止,我一直在创建 Web 音频节点,例如过滤器、振荡器等,同时创建 React 组件:
class Filter extends React.Component {
constructor(props) {
super(props);
const filter = props.context.createBiquadFilter();
this.state = { filter };
}
...
稍后,这意味着可以将过滤器作为组件状态的一部分进行更改:
frequencyChange(event) {
...
this.state.filter.frequency.setValueAtTime(range.value, context.currentTime);
}
并在渲染方法中:
<input type="range" className="slider" min={20} max={20000}
onChange={event => this.frequencyChange(event)}/>
但是,当谈到将过滤器链接在一起时,我需要能够 disconnect()
我从该组件的父 class 创建的网络音频过滤器节点,并且 connect()
它到一个新的目的地。
假设父组件称为 EffectsBox
,旨在呈现任意效果列表,如 Filter
。
它应该如何呈现所有这些组件,并允许它们公开一些常见的 API 以将音频链接在一起?
这些效果的状态(即网络音频组件)应该存储在哪里?
下面是一些示例代码,希望能使我的问题更清楚:
class EffectsBox extends React.Component {
...
addNewEffect(effect) {
// disconnect() the previous effect and connect() it to a new one
}
render() {
// Maybe some kind of "map" here between effects and react components?
return <div>{ this.state.effects }</div>
}
N.B。 – 我读过 React 的 refs
API,但它似乎不适合与任意数量的子 classes 一起使用 – 很高兴以其他方式展示!
React 不喜欢在不使用 setState
的情况下编辑组件状态中的值。我会避免将整个音频节点置于状态,甚至根本不置于组件中。
我曾经尝试在构造函数中将音频节点添加为 class 的一部分,这样我就可以像 this.filter
一样访问内容。然后我不得不 use refs everywhere 并将音频上下文传递给 everything 以访问连接节点和设置值所需的方法。它发出了我想要的声音,但我不喜欢我的文件如此紧密耦合和冗长。
我重构了一切。现在有一个文件使用管理所有音频节点的音频上下文。它公开了一些方法,我可以根据需要使用它来更新值。我还有一个字符串名称到节点的映射,所以我设置的值是这样的:setValue('filter', 'frequency', newValue)
。有少数情况需要单独处理(即失真曲线),但总体上对我来说更容易阅读。这种抽象还意味着您的音频节点对组件层次结构的变化不敏感。
这是我推荐的。将你的音频节点从你的 React classes 中拉出来。管理管理节点的代码要简单得多。