当使用react钩子进行全局状态管理时,如何将状态从类组件传递到全局状态

  • 本文关键字:状态 全局 组件 管理 react reactjs
  • 更新时间 :
  • 英文 :


对于我在React中构建的web应用程序,我需要录制音频,并且能够以某种方式将录制的音频放在应用程序的全局状态中,以便我可以在应用程序的不同组件中使用和操作录制的音频。

我的全局状态是使用React Hooks(由useReducer, createContext, useContext创建和管理)设置的,我相信Hooks只适用于功能组件,而不是类组件。

所以我遇到的问题是,我所遵循的每个教程让我的浏览器麦克风工作使用类组件(像下面的代码),而不是功能组件。我假设这是有充分理由的,因为当我试图将这些类组件转换为功能组件时,我得到了错误:&;无法读取'undefined'的属性'finish' &;

是否有办法采取这种音频数据(blobURL),并将其传递给我的全局状态?

或者(理想情况下),是否有一种方法可以使用麦克风在功能组件而不是类组件中记录音频?

import MicRecorder from "mic-recorder-to-mp3";
import React from "react";
const Mp3Recorder = new MicRecorder({ bitRate: 128 });
class AudioRecorder extends React.Component {
constructor(props) {
super(props);
window.AudioContext = window.AudioContext || window.webkitAudioContext;
this.state = {
isRecording: false,
isPaused: false,
blobURL: "",
isBlocked: false
};
}
startRecording = () => {
if (this.state.isBlocked) {
console.log("Please give permission for the microphone to record audio.");
} else {
Mp3Recorder.start()
.then(() => {
this.setState({ isRecording: true });
})
.catch(e => console.error(e));
}
};
stopRecording = () => {
this.setState({ isRecording: false });
Mp3Recorder.stop()
.getMp3()
.then(async ([buffer, blob]) => {
const blobURL = URL.createObjectURL(blob)
this.setState({ 
blobURL: blobURL,
isRecording: false
});
})
.catch(e => console.log(e));
};
checkPermissionForAudio = () => {
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function(constraints) {
// First get ahold of the legacy getUserMedia, if present
var getUserMedia =
// navigator.getUserMedia ||
navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// Some browsers just don't implement it - return a rejected promise with an error
// to keep a consistent interface
if (!getUserMedia) {
return Promise.reject(
new Error("getUserMedia is not implemented in this browser")
);
}
// Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
return new Promise(function(resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
};
}
navigator.mediaDevices
.getUserMedia({ audio: true })
.then(stream => {
this.setState({ isBlocked: false });
})
.catch(err => {
this.setState({ isBlocked: true });
console.log("Please give permission for the microphone to record audio.");      
console.log(err.name + ": " + err.message);
});
};
componentDidMount() {
this.checkPermissionForAudio();
}
render() {
const { isRecording } = this.state;
return (
<React.Fragment>
<button
onClick={this.startRecording}
className="mr-3 add-collec-btn"
disabled={isRecording}
>
Record
</button>
<button
onClick={this.stopRecording}
className="mr-3 delete-btn"
disabled={!isRecording}
>
Stop
</button>
<audio
ref="audioSource"
controls="controls"
src={this.state.blobURL || ""}
/>
</React.Fragment>
);
}
}
export default AudioRecorder;

更新:这就是我如何在我的应用程序中设置上下文,以及如何通过代码提供上下文。在我的store文件夹中,我有三个文件:Context.js、GlobalStateProvider和useGlobalState。

Context.js

import { createContext } from 'react';
const Context = createContext({});
export default Context;

GlobalStateProvider.js

这将我的App.js文件中的所有内容

import React from 'react';
import useGlobalState from './useGlobalState';
import Context from './Context';
const GlobalStateProvider = ({ children }) => {
return (
<Context.Provider value={useGlobalState()}>{children}</Context.Provider>
);
}
export default GlobalStateProvider;

useGlobalState.js

import { useReducer } from 'react';
const reducer = (state, action) => {
switch (action.type) {
case 'SETISRECORD':
return {
...state,
isRecording: action.payload
}
case 'SETISBLOCKED':
return {
...state,
isBlocked: action.payload
}
case 'setBlobURL':
return {
...state,
blobURL: action.payload
}
default: {
return state;
}
}
};
const useGlobalState = () => {
const [globalState, globalDispatch] = useReducer(reducer, {
isRecording: false,
isBlocked: false,
blobURL: '',
});
return { globalState, globalDispatch };
}
export default useGlobalState;

然后在功能组件中与我的全局状态接口,如下所示:

const functionalComponent = () => {  
const { globalState, globalDispatch } = useContext(Context);
return (
[code]
);
}

基于类的组件仍然可以"消费"。上下文,但语法比简单地使用useContextReact钩子要复杂一些。

上下文。消费者

对于您的情况,您将导入全局状态上下文Context,并呈现需要通过函数子访问上下文的组件。然后,子组件需要通过props来消费这些上下文值。

一些基于类的组件:

class MyComponent extends React.Component {
...
render() {
const { myContext: { globalState, globalDispatch } } = this.props;
return (
[code]
);
}
}

包装并通过props传递:

import MyContext from '../path/to/context';
...
<MyContext.Consumer>
{myContext => <MyComponent myContext={myContext} />}
</MyContext.Consumer>

最新更新