Building a recording app on React Type Script. I tried to set state with getting stream, and it seems to be successfully gotten on console. But it couldn't be set up on record target stream
.
const [recordTargetStream, setRecordTargetStream] = useState<MediaStream>()
// click request permissions
const requestPermissions = useCallback(async() => {
const stream = await window.navigator.mediaDevices.getUserMedia({audio: true, video: true})
// stream is successfully gotten
setRecordTargetStream(stream)
}, [])
const startRecording = useCallback(() => {
console.log('start recording', recordTargetStream)
// record target stream is undefined
...
return (
<>
<button onClick={() => requestPermissions()}>Request permissions</button>
<button onClick={() => startRecording()}>Start recording</button>
</>
)
CodePudding user response:
You should use the recordTargetStream
state as useCallback
hook's dependencies.
useCallback
will return a memoized version of the callback that only changes if one of the dependencies has changed.
every value referenced inside the callback should also appear in the dependencies array.
index.tsx
:
import React, { useCallback, useState } from 'react'
export default function MyComponent() {
const [recordTargetStream, setRecordTargetStream] = useState<MediaStream>()
const requestPermissions = useCallback(async() => {
const stream = await window.navigator.mediaDevices.getUserMedia({audio: true, video: true})
setRecordTargetStream(stream)
}, [])
const startRecording = useCallback(() => {
console.log('start recording', recordTargetStream)
}, [recordTargetStream])
return (
<>
<button onClick={() => requestPermissions()}>Request permissions</button>
<button onClick={() => startRecording()}>Start recording</button>
</>
)
}
index.test.tsx
:
import {fireEvent, render, screen, act} from '@testing-library/react';
import React from 'react';
import MyComponent from './';
describe('69354798', () => {
test('should pass', async () => {
const mockMediaDevices = {
getUserMedia: jest.fn().mockResolvedValue('test stream')
}
Object.defineProperty(window.navigator, 'mediaDevices', {
value: mockMediaDevices
})
render(<MyComponent/>)
await act(async () => {
fireEvent.click(screen.getByText(/Request permissions/))
})
fireEvent.click(screen.getByText(/Start recording/))
})
})
test result:
PASS stackoverflow/69354798/index.test.tsx
69354798
✓ should pass (54 ms)
console.log
start recording test stream
at stackoverflow/69354798/index.tsx:12:13
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 3.211 s