Warning: Can't perform a React state update on an unmounted component, no-op, but it indicates a memory leak in your application - unmount

I fetch the data from api (in localhost:4001/) and i got the data in my console but it is not listing and it shows error " Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. " and also shows another error " Category.js:59 Uncaught TypeError: category.map is not a function".
This is my code.
//enter code here
import React, { useEffect, useState } from "react";
import axios from "axios";
function Category() {
const [category , setCategory]=useState([]);
const getCategoryData= async () =>{
try{
const data= await axios.get("http://localhost:4001/category");
console.log(data.data);
setCategory(data.data);
}
catch(e){
console.log(e);
}
}
useEffect(() =>{
let isCancelled = false;
getCategoryData();
return () => {
isCancelled = true;
};
} ,[]);
return(
<>
<h2 style={{textAlign:"center"}}>Category List</h2>
{category.map((item)=>{
return <p>{item.id}-{item.category_name}</p>
})}
</>
);
}
export default Category;

Related

How to play audio from server use expo-av in react-native

I try to play video from server. This is my code:
import React, {useState, useEffect} from 'react';
import { Button } from 'react-native';
import { Audio } from 'expo-av';
export default function App() {
const [audioStatus, setAudioStatus] = useState(false)
const [sound, setSound] = useState(new Audio.Sound());
useEffect(()=>{
(async () => {
console.log('status', audioStatus)
if (audioStatus) {
await sound.loadAsync('https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3')
try {
await sound.playAsync()
} catch (e) {
console.log(e)
}
}else {
await sound.stopAsync()
await sound.unloadAsync()
}
})()
},[audioStatus])
return (
<Button color={audioStatus ? 'red' : 'green'} title={'play'} onPress={()=>setAudioStatus(!audioStatus)} />
);
}
And I get error:
LOG status false
WARN Possible Unhandled Promise Rejection (id: 15):
Error: Cannot complete operation because sound is not loaded.
http://192.168.100.60:19000/node_modules/expo/AppEntry.bundle?platform=android&dev=true&hot=false:100133:28
generatorResume#[native code]
asyncGeneratorStep#http://192.168.100.60:19000/node_modules/expo/AppEntry.bundle?platform=android&dev=true&hot=false:20982:26
It looks like your post is mostly code; please add some more details.It looks like your post is mostly code; please add some more details.

Expo Audio.Recording Cannot read property 'uri' of undefined

I'm trying to start a new recording in Expo react native but for some odd reason the app crashes.
The code i written is pretty much copy paste from the official expo docs.
import React, { useState, useEffect } from 'react';
import { Audio } from 'expo-av';
import PitchFinder from "pitchfinder";
import { StyleSheet, Text, View, Button } from 'react-native';
const Tuner = () => {
const pitchFinder = new PitchFinder.YIN();
const start = async () => {
const recording = new Audio.Recording();
console.log(recording)
await recording.prepareToRecordAsync(Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY);
await recording.startAsync();
const audio_stream = recording.getURI();
console.log(audio_stream);
await recording.stopAndUnloadAsync();
}
return (
<View>
<Button title="Start recording" onPress={() => start()} />
</View>
)
};
export default Tuner;
The app crashes at await recording.prepareToRecordAsync(Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY);
with the error
Unhandled Rejection (TypeError): Cannot read property 'uri' of undefined
please check Expo documentation again
check permission
https://docs.expo.io/versions/latest/sdk/audio/
try with
const recording = new Audio.Recording();
try {
await recording.prepareToRecordAsync(Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY);
await recording.startAsync();
// You are now recording!
} catch (error) {
// An error occurred!
}

React native unhandled promise rejection p0

Hello i get the above error when i run my project what am i doing wrong?
import * as WebBrowser from 'expo-web-browser';
import React , {Component} from 'react';
import {PermissionsAndroid} from 'react-native';
import {
Image,
Platform,
ScrollView,
StyleSheet,
Text,
Button,
TouchableOpacity,
View,
Switch
} from 'react-native';
import { MonoText } from '../components/StyledText';
import {Linking , SMS }from 'expo';
import * as Permissions from 'expo-permissions'
class Sendsms extends Component {
state = {switch1Value: false}
toggleSwitch1 = (value) => {
this.setState({switch1Value: value});
console.log('Switch 1 is: ' + value);
}
askSMSPermissionsAsync = async () => {
await Permissions.askAsync(Permissions.SMS);
};
HandlePress = () =>{
console.log('try to send sms');
}
render(){
return(
<View>
<Text>{this.state.switch1Value ? 'Switch is ON' : 'Switch is OFF'}</Text>
<Switch onValueChange = {this.toggleSwitch1.bind(this)} value = {this.state.switch1Value}/>
<Button title="sendSMS" onPress={this.askSMSPermissionsAsync} />
</View>
)
}
}
I tried rebulding project and deleting the build folder with no luck
I also tried to copy the code in some other project still same error
export default Sendsms;
You need to wrap your await call in a try/catch to handle the rejected promise. I'm not sure why it's getting rejected but you could console.log to find out by doing:
askSMSPermissionsAsync = async () => {
try {
await Permissions.askAsync(Permissions.SMS);
} catch(e) {
console.log(e);
}
};
Remember that await is just syntactic sugar for a promise.
await Permissions.askAsync(Permissions.SMS); results into a Promise which might be rejected. When using promises, always use a try {} catch(e) {} to catch any rejections.
Check the logging for more info about the rejection.
So:
askSMSPermissionsAsync = async () => {
try {
await Permissions.askAsync(Permissions.SMS);
} catch (e) {
console.error(e);
}
};

Persisting data between app launches with Expo & React Native

Here's my App.js, everything else is as standard/simple as I can get it.
import React from 'react';
import { AsyncStorage, Text, View } from 'react-native';
export default class App extends React.Component {
render() {
console.log("Fetching data")
AsyncStorage.getItem('#MySuperStore:key', (value) => {
console.log("Fetched data: ", value)
if(value == null) {
console.log("Writing data!")
AsyncStorage.setItem('#MySuperStore:key', 'data', () => {
console.log("Wrote data!")
})
}
})
return(
<View>
<Text>Hello, ReplIt</Text>
</View>
);
}
}
The fetched value is always null.
I've tried this both locally and on ReplIt. In all cases, the data does not persist across app loads; I always see:
Fetching data
Fetched data: null
Writing data!
Wrote data!
What am I doing wrong? Do I have an incorrect assumption about how Expo interacts with the persistent storage? AFAIK, AsyncStorage is supposed to save stuff to the device; so I can close and re-open the app and have the data persist.
UPD: i just realized your code worked as expected... probably it is replit issue as mentioned in comment.
Avoid any requests and async calls in render method, because it could be called may times depending on how props or state changing. Better put all related code into componentDidMount as it is recommended in documentation. It will be called only once when component mounted.
Not sure why your code dodnt worked for you, callbacks are allowed for AsyncStorage, however wait works just fine for me:
import React from "react";
import { AsyncStorage, Text, View } from "react-native";
export default class App extends React.Component {
constructor() {
super();
this.state = {
storedValue: null
};
}
async componentDidMount() {
let storedValue = await AsyncStorage.getItem("#MySuperStore:key");
console.log("Fetched data: ", storedValue);
if (storedValue == null) {
console.log("Writing data!");
storedValue = await AsyncStorage.setItem("#MySuperStore:key", "data");
}
this.setState({
storedValue
});
}
render() {
const { storedValue } = this.state;
return (
<View>
<Text>Hello, ReplIt</Text>
<Text>This is Stored Value, '{storedValue}'</Text>
</View>
);
}
}
give these a try. AsyncStorage is a Javascript Promise based method.
AsyncStorage.getItem('#MySuperStore:key')
.then(value => console.log(value))
or
value = await AsyncStorage.getItem('#MySuperStore:key');
console.log(value);

React Native AsyncStorage fetches data after rendering

I am using AsyncStorage in ComponentWillMount to get locally stored accessToken, but it is returning the promise after render() function has run. How can I make render() wait until promise is completed? Thank you.
You can't make a component wait to render, as far as I know. What I've done in the app I'm working on is to add a loading screen until that promise from AsyncStorage resolves. See the examples below:
//
// With class component syntax
//
import React from 'react';
import {
AsyncStorage,
View,
Text
} from 'react-native';
class Screen extends React.Component {
state = {
isLoading: true
};
componentDidMount() {
AsyncStorage.getItem('accessToken').then((token) => {
this.setState({
isLoading: false
});
});
},
render() {
if (this.state.isLoading) {
return <View><Text>Loading...</Text></View>;
}
// this is the content you want to show after the promise has resolved
return <View/>;
}
}
//
// With function component syntax and hooks (preferred)
//
import React, { useEffect } from 'react';
import {
AsyncStorage,
View,
Text
} from 'react-native';
const Screen () => {
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
AsyncStorage.getItem('accessToken').then((token) => {
setIsLoading(false);
});
}, [])
if (isLoading) {
return <View><Text>Loading...</Text></View>;
}
// this is the content you want to show after the promise has resolved
return <View/>;
}
Setting the isLoading property in state will cause a re-render and then you can show the content that relies on the accessToken.
On a side note, I've written a little library called react-native-simple-store that simplifies managing data in AsyncStorage. Hope you find it useful.
Based on react-native doc, you can do something like this:
import React, { Component } from 'react';
import {
View,
} from 'react-native';
let STORAGE_KEY = '#AsyncStorageExample:key';
export default class MyApp extends Component {
constructor(props) {
super(props);
this.state = {
loaded: 'false',
};
}
_setValue = async () => {
try {
await AsyncStorage.setItem(STORAGE_KEY, 'true');
} catch (error) { // log the error
}
};
_loadInitialState = async () => {
try {
let value = await AsyncStorage.getItem(STORAGE_KEY);
if (value === 'true'){
this.setState({loaded: 'true'});
} else {
this.setState({loaded: 'false'});
this._setValue();
}
} catch (error) {
this.setState({loaded: 'false'});
this._setValue();
}
};
componentWillMount() {
this._loadInitialState().done();
}
render() {
if (this.state.loaded === 'false') {
return (
<View><Text>Loading...</Text></View>
);
}
return (
<View><Text>Main Page</Text></View>
);
}
}
you can use react-native-easy-app that is easier to use than async storage.
this library is great that uses async storage to save data asynchronously and uses memory to load and save data instantly synchronously, so we save data async to memory and use in app sync, so this is great.
import { XStorage } from 'react-native-easy-app';
import { AsyncStorage } from 'react-native';
const initCallback = () => {
// From now on, you can write or read the variables in RNStorage synchronously
// equal to [console.log(await AsyncStorage.getItem('isShow'))]
console.log(RNStorage.isShow);
// equal to [ await AsyncStorage.setItem('token',TOKEN1343DN23IDD3PJ2DBF3==') ]
RNStorage.token = 'TOKEN1343DN23IDD3PJ2DBF3==';
// equal to [ await AsyncStorage.setItem('userInfo',JSON.stringify({ name:'rufeng', age:30})) ]
RNStorage.userInfo = {name: 'rufeng', age: 30};
};
XStorage.initStorage(RNStorage, AsyncStorage, initCallback);
React-native is based on Javascript which does not support blocking functions.Also this makes sense as we don't want the UI to get stuck or seem unresponsive.
What you can do is handles this in the render function. i.e Have a loading screen re-render it as you as you get the info from the AsyncStorage