How to make speech to text in react native? - javascript

I need to make recognition in russian language, now I am trying to do it in English. I get this exception:
[TypeError: null is not an object (evaluating 'Voice.startSpeech')]
This is my code react-native app with the error:
const Train = () => {
const [user] = useAuth()
const [pitch, setPitch] = useState('');
const [error, setError] = useState('');
const [end, setEnd] = useState('');
const [started, setStarted] = useState('');
const [results, setResults] = useState([]);
const [partialResults, setPartialResults] = useState([]);
useEffect(() => {
//Setting callbacks for the process status
Voice.onSpeechStart = onSpeechStart;
Voice.onSpeechEnd = onSpeechEnd;
Voice.onSpeechError = onSpeechError;
Voice.onSpeechResults = onSpeechResults;
Voice.onSpeechPartialResults = onSpeechPartialResults;
Voice.onSpeechVolumeChanged = onSpeechVolumeChanged;
return () => {
//destroy the process after switching the screen
Voice.destroy().then(Voice.removeAllListeners);
};
}, []);
const onSpeechStart = (e) => {
//Invoked when .start() is called without error
console.log('onSpeechStart: ', e);
setStarted('√');
};
const onSpeechEnd = (e) => {
//Invoked when SpeechRecognizer stops recognition
console.log('onSpeechEnd: ', e);
setEnd('√');
};
const onSpeechError = (e) => {
//Invoked when an error occurs.
console.log('onSpeechError: ', e);
setError(JSON.stringify(e.error));
};
const onSpeechResults = (e) => {
//Invoked when SpeechRecognizer is finished recognizing
console.log('onSpeechResults: ', e);
setResults(e.value);
};
const onSpeechPartialResults = (e) => {
//Invoked when any results are computed
console.log('onSpeechPartialResults: ', e);
setPartialResults(e.value);
};
const onSpeechVolumeChanged = (e) => {
//Invoked when pitch that is recognized changed
console.log('onSpeechVolumeChanged: ', e);
setPitch(e.value);
};
const startRecognizing = async () => {
//Starts listening for speech for a specific locale
try {
await Voice.start('en-US');
setPitch('');
setError('');
setStarted('');
setResults([]);
setPartialResults([]);
setEnd('');
} catch (e) {
//eslint-disable-next-line
console.error(e);
}
};
const stopRecognizing = async () => {
//Stops listening for speech
try {
await Voice.stop();
} catch (e) {
//eslint-disable-next-line
console.error(e);
}
};
const cancelRecognizing = async () => {
//Cancels the speech recognition
try {
await Voice.cancel();
} catch (e) {
//eslint-disable-next-line
console.error(e);
}
};
const destroyRecognizer = async () => {
//Destroys the current SpeechRecognizer instance
try {
await Voice.destroy();
setPitch('');
setError('');
setStarted('');
setResults([]);
setPartialResults([]);
setEnd('');
} catch (e) {
//eslint-disable-next-line
console.error(e);
}
};
return (
<View style={styles.container}>
<View style={styles.header}>
<Image
source={require('../assets/images/Logo_small.png')}
style={styles.logo_s}
resizeMode='contain'/>
</View>
<View style={styles.main_cont}>
<Train_word marginBottom={34}/>
<Train_word_2 marginBottom={55}/>
<Pressable marginBottom={190} onPress={startRecognizing}>
<Image
source={require('../assets/images/Start_img.png')}
style={styles.start_img}>
</Image>
</Pressable>
<Pressable style={styles.result} onPress={''}>
<Text style={styles.text_result}>Получить результат</Text>
</Pressable>
</View>
</View>
)
}
The code Always takes the exception. I do not know how to solve it.
How can I fix this and make speech to text in russian language. Help me please, I am a beginner in react native.

Related

How do I rerender a FlatList when a value of an object changes?

The idea is to have a toggle switch that switches from To Watch and Watched bookings. When I update a movie in the To Watch list, I want it to rerender the FlatList without that booking because it's now in the Watched list. And so when I press the toggle to see the Watched list I would now see the booking there. Same for reverse. This is the code I have:
const WatchList = () => {
const uid = auth.currentUser.uid;
const docRef = doc(db, 'users', uid);
const [user, setUser] = useState({});
const [watched, setWatched] = useState(true);
const [text, setText] = useState('To watch');
const [filteredBookings, setFilteredBookings] = useState(bookings);
const bookingsRef = collection(db, "booking"); // imamo ref ka bazi
const [bookings, setBookings] = useState({});
useEffect(() => {
getUser();
getBookings();
},[])
const getUser = async () => {
const snap = await getDoc(docRef)
setUser({user, ...snap.data()})
}
const getBookings = async () =>{
const q = query(bookingsRef, where("users","array-contains",auth.currentUser.uid));
const unsubscribe = onSnapshot(q, (querySnapshot) => {
const a = [];
querySnapshot.forEach((doc) => {
a.push(doc.data());
});
setBookings(querySnapshot.docs);
});
}
const toggleSwitch = () =>{
if(!watched){
setFilteredBookings(bookings.filter(function(item){
return item.data().watched == true;
}))
setText('Watched');
} else {
setText('To watch');
setFilteredBookings(bookings.filter(function(item){
return item.data().watched == false;
}))
}
setWatched(previousState => !previousState);
}
const updateBooking = async(id) => {
try {
await setDoc(doc(db, 'booking', id), {
watched: true
}, {merge: true})
}
catch(e) {
console.log(e)
}
}
const updateBooking1 = async(id) => {
try {
await setDoc(doc(db, 'booking', id), {
watched: false
}, {merge: true})
}
catch(e) {
console.log(e)
}
}
const deleteBooking = async(id) => {
try {
await deleteDoc(doc(db, 'booking', id));
}
catch(e) {
console.log(e)
}
}
useEffect(() => {
const resultOfFiltering = bookings
setFilteredBookings(resultOfFiltering)
}, [bookings])
return (
<View>
<View>
<Text>{text}</Text>
<Switch
value = {watched}
/>
</View>
<FlatList
data = {filteredBookings}
renderItem = {({item}) => (
<View>
<View>
<Text>{item.data().movie}</Text>
<Text>{item.data().day} - {item.data().showtime}</Text>
</View>
<View>
{item.data().watched == true ? (
<TouchableOpacity style = {styles.delete} onPress = {() => {updateBookings(item.id); setFilteredBookings();}}>
<Image source={require('../assets/watched.png')}/>
</TouchableOpacity>
) : (
<TouchableOpacity onPress = {() => {updateBookings1(item.id); setFilteredBookings();}}>
<Image source={require('../assets/towatch.png')}/>
</TouchableOpacity>)}
<TouchableOpacity onPress = {() => {deleteBooking(item.id); setFilteredBookings();}}>
<Image source={require('../assets/remove.png')}/>
</TouchableOpacity>
</View>
</View>
)}
/>
</View>
)
}
export default WatchList
It's not really working properly at the moment and I'm not sure what I'm doing wrong so I'm kind of stuck. If I could get some help, I'd really appreciate it. Thank you!

How do I get a FlatList to show correct items when I open the screen?

The idea is to have a toggle switch that switches from To Watch and Watched bookings. When I update a movie in the To Watch list, I want it to rerender the FlatList without that booking because it's now in the Watched list. And so when I press the toggle to see the Watched list I would now see the booking there. Same for reverse.
I have to press the toggle twice to see the change. Even when I open the screen for the first time it shows all the movies without the filter - this is the main thing I'm having trouble with. How can I get around this? This is the code I have:
const WatchList = () => {
const uid = auth.currentUser.uid;
const docRef = doc(db, 'users', uid);
const [user, setUser] = useState({});
const [watched, setWatched] = useState(true);
const [text, setText] = useState('To watch');
const [filteredBookings, setFilteredBookings] = useState(bookings);
const bookingsRef = collection(db, "booking"); // imamo ref ka bazi
const [bookings, setBookings] = useState({});
useEffect(() => {
getUser();
getBookings();
},[])
const getUser = async () => {
const snap = await getDoc(docRef)
setUser({user, ...snap.data()})
}
const getBookings = async () =>{
const q = query(bookingsRef, where("users","array-contains",auth.currentUser.uid));
const unsubscribe = onSnapshot(q, (querySnapshot) => {
const a = [];
querySnapshot.forEach((doc) => {
a.push(doc.data());
});
setBookings(querySnapshot.docs);
});
}
const toggleSwitch = () =>{
if(!watched){
setFilteredBookings(bookings.filter(function(item){
return item.data().watched == true;
}))
setText('Watched');
} else {
setText('To watch');
setFilteredBookings(bookings.filter(function(item){
return item.data().watched == false;
}))
}
setWatched(previousState => !previousState);
}
const updateBooking = async(id) => {
try {
await setDoc(doc(db, 'booking', id), {
watched: true
}, {merge: true})
}
catch(e) {
console.log(e)
}
}
const updateBooking1 = async(id) => {
try {
await setDoc(doc(db, 'booking', id), {
watched: false
}, {merge: true})
}
catch(e) {
console.log(e)
}
}
const deleteBooking = async(id) => {
try {
await deleteDoc(doc(db, 'booking', id));
}
catch(e) {
console.log(e)
}
}
useEffect(() => {
const resultOfFiltering = bookings
setFilteredBookings(resultOfFiltering)
}, [bookings])
return (
<View>
<View>
<Text>{text}</Text>
<Switch
value = {watched}
/>
</View>
<FlatList
data = {filteredBookings}
extraData = {watched}
renderItem = {({item}) => (
<View>
<View>
<Text>{item.data().movie}</Text>
<Text>{item.data().day} - {item.data().showtime}</Text>
</View>
<View>
{item.data().watched == true ? (
<TouchableOpacity style = {styles.delete} onPress = {() => {updateBookings(item.id); setFilteredBookings();}}>
<Image source={require('../assets/watched.png')}/>
</TouchableOpacity>
) : (
<TouchableOpacity onPress = {() => {updateBookings1(item.id); setFilteredBookings();}}>
<Image source={require('../assets/towatch.png')}/>
</TouchableOpacity>)}
<TouchableOpacity onPress = {() => {deleteBooking(item.id); setFilteredBookings();}}>
<Image source={require('../assets/remove.png')}/>
</TouchableOpacity>
</View>
</View>
)}
/>
</View>
)
}
export default WatchList
It's not really working properly at the moment and I'm not sure what I'm doing wrong so I'm kind of stuck. If I could get some help, I'd really appreciate it. Thank you!

How to implement multiple functions on a single event handler?

I have this simple react native app that on button click it redirects user to a page. I'm saving data in a cache so that if user clicks the store button it stores data and after refresh it sets store data. However, I would like to implement this logic on a single button, not on 2 different buttons as it is now. Can someone explain me how could I achieve this?
export const App = () => {
const [showFirstWeb, setFirstWeb] = useState(false);
const getData = async () => {
try {
const jsonValue = await AsyncStorage.getItem("#web_Key");
return setFirstWeb(JSON.parse(jsonValue));
} catch (e) {
console.log("error", e);
}
};
useEffect(() => getData, []);
const storeData = async () => {
try {
const jsonValue = JSON.stringify(showFirstWeb);
await AsyncStorage.setItem("#web_Key", jsonValue);
} catch (e) {
console.log("error", e);
}
};
return (
<View>
<View style={styles.buttonStyle}>
<Button onPress={setFirstWeb(!showFirstWeb)}/>
<Button onPress={storeData} title="store"/>
<View>
{showFirstWeb && <MyWebComponent uri="https://www.google.com/" />}
</View>
</View>
);
};
const MyWebComponent = (uri) => {
return <WebView source={uri} />;
};```
export const App = () => {
const [showFirstWeb, setFirstWeb] = useState(false);
const getData = async () => {
try {
const jsonValue = await AsyncStorage.getItem("#web_Key");
return setFirstWeb(JSON.parse(jsonValue));
} catch (e) {
console.log("error", e);
}
};
// you forgot to call the function here
useEffect(() => getData(), []);
const storeData = async () => {
try {
// get the new value
const newShowFirstWeb = !showFirstWeb
// use the new value
setFirstWeb(newShowFirstWeb)
const jsonValue = JSON.stringify(newShowFirstWeb );
await AsyncStorage.setItem("#web_Key", jsonValue);
} catch (e) {
console.log("error", e);
}
};
return (
<View>
<View style={styles.buttonStyle}>
<Button onPress={storeData} title="store"/>
<View>
{showFirstWeb && <MyWebComponent uri="https://www.google.com/" />}
</View>
</View>
);
};

How do I make a function run again if, and only if, it returns null in React Native?

I have a RN/Expo project that, at times, returns a null value because the data just hasn't had the time to load.
The data is coming from an AWS server.
If I refresh the page, this will normally fix itself, however this is not a long term solution.
How can I modify this function so that it will run again, if, and only if, it returns a "null" response for any of the variables?
Below is my code:
const [ firstName, getFirstName ] = useState('')
const [ phone, getPhone ] = useState('')
const [ email, getEmail ] = useState('')
const [ userPhoto, getUserPhoto ] = useState(null)
useEffect(()=>{
const info_response = server_grab.get_user_info().then(response=>{
const displayName = async()=>{
getFirstName(
<Text style = {styles.title}>
{response.first_name} {response.last_name}
</Text>
)
getPhone(
<Text style = {styles.box_text}>
{response.phone}
</Text>
)
getEmail(
<Text style = {styles.box_text}>
{response.email}
</Text>
)
}
)
}
const displayPhoto = async () =>{
const photo_response = server_grab.download_profile_photo().then(response=>{
getUserPhoto(response.photo_data.raw_data)
}
)
}
displayPhoto()
displayName()
...
return(
<View>
{userPhoto && <Avatar.Image source= {{uri:`data:image/jpg;base64,${userPhoto}`}}/>}
</View>
<View>
<Text>{firstName}</Text>
<Text>{email}</Text>
<Text>{phone}</Text>
</View>
)
This is an example of the concept you could use:
import { Text, View, Image, ActivityIndicator } from 'react-native';
const simulateApiCall = (type, timeout = 1000 ) => new Promise((resolve, reject) => {
setTimeout(() => {
switch(type){
case "firstName":
resolve('John');
break;
case 'lastName':
resolve('Doe');
break;
case 'avatar':
resolve('https://cdn1.vectorstock.com/i/1000x1000/31/95/user-sign-icon-person-symbol-human-avatar-vector-12693195.jpg');
break;
}
}, timeout);
});
const Home = () => {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [userAvatar, setUserAvatar] = useState(null);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
loadUserData();
}, [loadUserData]);
const loadUserData = useCallback(async () => {
setIsLoading(true);
try {
const userFirstName = await simulateApiCall('firstName');
const userLastName = await simulateApiCall('lastName');
setFirstName(userFirstName ?? '');
setLastName(userLastName ?? '');
setIsLoading(false);
loadUserAvatar();
} catch (error) {
setIsLoading(false);
console.log('Error loading user data');
}
}, [loadUserAvatar]);
const loadUserAvatar = useCallback(async () => {
try {
const userAvatar = await simulateApiCall('avatar', 2000);
setUserAvatar(userAvatar);
} catch(error){
console.log('Error loading user avatar')
}
}, []);
return(<View>
{isLoading ? <ActivityIndicator /> :
<>
{userAvatar && <Text>{userAvatar}</Text>}
<Text>{firstName}</Text>
<Text>{lastName}</Text>
</>
}
</View>);
}
export default Home;
You can play around here https://snack.expo.dev/#steppannws/d39758

null reference exception while passing event handler in react

i want to send message while typing text by using websocket.
but have websocket reference error while typing text.
i think ShareTextComponent onInputEvent function parameter is not exeucte in another location.
so websocket property can't reference in this field
but i don't know how can i fix it.
and i didn't use any state management library such as redux and mobx.
just pure reactjs
[error]
[code]
const ShareTextComponentView = (props) => {
const [isShareMode, setShareMode] = useState(false)
const [syncText, setSyncText] = useState("")
const [isOpen, setOpen] = useState(false)
const [name, setName] = useState("")
let ws = null;
const connect = () => {
ws = new WebSocket(ADDRESS + `/${name}`)
//액세스코드들을 전부 보냄
ws.onopen = () => {
ws.send(JSON.stringify({command: "CONNECT", accessCode: generateAccessCode()}))
console.log(`${ADDRESS}에 접속 되었습니다.`)
setOpen(true)
}
ws.onclose = () => {
ws.send(JSON.stringify({command: "CLOSE"}))
console.log(`${ADDRESS}에 접속 종료 되었습니다.`)
setOpen(false)
}
ws.onmessage = (evt) => {
if (isShareMode) {
return
}
const message = JSON.parse(evt.data)
console.log({message: message})
setSyncText(message.data)
}
ws.onerror = (err) => {
console.log("접속중에 에러가 발생되었습니다.")
console.log(err)
}
}
const close = () => {
if (ws !== null && ws.readyState !== WebSocket.CLOSED) {
ws.close()
}
}
// p2p로 웹소켓으로 연결
useEffect(() => {
if (isOpen) {
return
}
connect()
setOpen(true)
return () => {
//만약 공유모드를 종료했을때 websocket에 shutdown 메세지를 보냄
if (isOpen) {
close()
console.log(`${ADDRESS}에 접속 종료 되었습니다.`)
}
setOpen(false)
}
}, [isShareMode])
const onTextInput = (text) => {
const {name, value} = text.target
if (!isShareMode) {
return
}
console.log("websocket status")
console.log(ws)
console.log("input value")
console.log(value)
if (ws.readyState === WebSocket.CLOSED) {
console.log("Connect Close 되었습니다.")
} else {
ws.send(JSON.stringify({command: "SEND", message: value}))
}
}
const generateAccessCode = () => {
return "hello"
}
const reconnect = () => {
connect()
console.log(ws)
}
return (
<div className="container">
<h1> Please Enter This Area Section</h1>
<h1> {isOpen ? "Connect" : "Disconnect"}</h1>
<div className="name-container">
<label> Name : </label>
<input type="text" onChange={(e) => {
setName(e.target.value)
}}/>
</div>
<button className="reconnect-mode" onClick={reconnect}>Connect</button>
<button className="is-receiever" onClick={() => setShareMode(!isShareMode)}>공유자 입니까?</button>
<h1>{isShareMode ? "공유모드" : "수신모드"}</h1>
<ShareTextComponent accessCode={generateAccessCode()} onInputEvent={onTextInput} syncText={syncText}/>
</div>
)
}
export default ShareTextComponentView;
[after logging in onTextInput]
Add a null check to the top of the function ->
const onTextInput = (text) => {
if (!ws) return;
This will at least help you get past that error and narrow down the rest of the flow.

Categories