i am trying to add some speech recognition to my react app. If the user says a specific word - 'frog', it allows them to open the next page. However I am stuck in adding this line to my page, because it is a hook it isn't allowed:
const { transcript, resetTranscript } = useSpeechRecognition();
Is there a way to add it without creating a new component, as the button on this page needs to know what has been said and whether to allow the user to proceed.
Below is my code:
export const AuthPage = () => {
const navigate = useNavigate();
//THIS LINE IS CAUSING THE HOOK ERROR
// const { transcript, resetTranscript } = useSpeechRecognition();
const navigateToNextPage = () => {
navigate(`/frogPage/${name}`);};
return (
<main className='simple-wrapper'>
<button onClick={SpeechRecognition.startListening}>Say Word</button>
//ONLY SHOW NEXT BUTTON IF THEY SAID THE WORD FROG CORRECTLY
{transcript.includes("frog") && (
<button onClick={navigateToNextPage}>Next</button>)
</main>
);
};
Ok! So, I tried this out and the only thing giving error. I did encounter was with useNavigate for some reason. So, I switched to react-router-dom@5.2.0 due to more familiarity.
Upon reading the NPM documentation for it (doc). This might be dependent on your browser too. So, it does recommends adding polyfill to it but updated chrome should support this.(due to the Web Speech API)
I am using react-speech-recognition (3.9.0) and react version17.0.2. Also, the react-speech-recognition library requires React 16.8 or greater for the React hooks to be used
Below is the full code which worked for me
// AuthPage.js
import SpeechRecognition, {
useSpeechRecognition
} from "react-speech-recognition";
import { useHistory } from "react-router-dom";
const AuthPage = () => {
const history = useHistory(); // usehistory in place of useNavigate
// const navigate = useNavigate();
const { transcript, resetTranscript } = useSpeechRecognition();
const navigateToNextPage = () => {
console.log("This works");
history.push("/homepage");
// navigate(`/frogPage/${name}`);
};
return (
<main className="simple-wrapper">
<button onClick={SpeechRecognition.startListening}>Say Word</button>
{/* //ONLY SHOW NEXT BUTTON IF THEY SAID THE WORD FROG CORRECTLY */}
{transcript.includes("frog") && (
<button onClick={navigateToNextPage}>Next</button>
)}
</main>
);
};
export default AuthPage;
Just incase if you want to test it out yourself. The below is the App page I added which should work and should display the Say Word button and after the speechrecognition by saying 'frog' it provides a way to navigate to the homepage.
// App.js
import React from "react";
import AuthPage from "./AuthPage";
import Homepage from "./Homepage";
import { BrowserRouter, Switch, Route } from "react-router-dom";
// const SpeechlySpeechRecognition = createSpeechlySpeechRecognition(appId);
// SpeechRecognition.applyPolyfill(SpeechRecognitionPolyfill);
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div>{/* <Dictaphone /> */}</div>
<BrowserRouter>
<Switch>
<Route exact path="/">
<AuthPage />
</Route>
<Route exact path="/homepage">
<Homepage />
</Route>
</Switch>
</BrowserRouter>
</div>
);
}
// Homepage.js
import React from "react";
const Homepage = (props) => {
return <div>Homepage</div>;
};
export default Homepage;
Also, Link to the solution working link . Also, Keep in mind you need to allow your microphone on the webpage :)
judging from your feedback it looks like you are trying to use hooks inside a class component.
solution: create a wrapper component
function WrapperComponent({ renderChild }) {
const result = useSpeechRecognition();
return renderChild(result)
}
class MyComponent {
render() {
return <WrapperComponent
renderChild={({ transcript, resetTranscript }) => (
<main className='simple-wrapper'>
<button onClick={SpeechRecognition.startListening}>Say Word</button>
//ONLY SHOW NEXT BUTTON IF THEY SAID THE WORD FROG CORRECTLY
{transcript.includes("frog") && (
<button onClick={navigateToNextPage}>Next</button>)
</main>
)}
/>
}
}
you may even use props.children(as a function) directly if you want. use whatever is comfortable.