Hash value null error in react-native hooks useEffect - react-native

the hash data I received using asyncStorage in my react native project is wrong. It actually works when I refresh the page. My request is probably running earlier than hash. However, I could not find a solution to this.
const [info, setInfo] = useState('');
const [hash, setHash] = useState(null);
const _retrieveData = async () => {
try {
const value = await AsyncStorage.getItem('hash');
setHash(value)
} catch (error) {
// Error retrieving data
}
};
useEffect(() => {
_retrieveData()
setTimeout(() => {
console.log(hash) //
axios.get(apiUrl + 'loginInfo?hash=' + hash)
.then(response => {
setInfo(response.data.message);
console.log('res', response);
});
}, 1000);
}, []);

The _retriveData method should be inside of the useEffect.
const [info, setInfo] = useState('');
const [hash, setHash] = useState(null);
useEffect(() => {
const _retrieveData = async () => {
try {
const hash = await AsyncStorage.getItem('hash');
return hash
} catch (error) {
console.log('error',error);
// Error retrieving data
}
};
const hash = _retrieveData()
setTimeout(() => {
console.log(hash) //
axios.get(apiUrl + 'loginInfo?hash=' + hash)
.then(response => {
setInfo(response.data.message);
console.log('res', response);
});
}, 1000);
}, []);

I solved the problem by getting help from a friend.
const [info, setInfo] = useState({});
const [hash, setHash] = useState(null);
const _retrieveData = useCallback(async () => {
try {
const value = await AsyncStorage.getItem('hash');
setHash(value);
} catch (error) {
// Error retrieving data
}
}, []);
const getInfo = useCallback(async () => {
try {
const response = await axios.get(apiUrl + 'loginInfo?hash=' + hash);
setInfo(response.data.message)
} catch (e) {
console.log(e);
}
}, [hash]);
useEffect(() => {
if (!hash) {
_retrieveData();
}
}, [hash])
useEffect(() => {
if (hash) {
setTimeout(() => {
getInfo();
},500)
}
}, [hash, getInfo]);

Related

asyncstorage with useReducer does not save the values

i am new to reactnative, i was trying to build todo app using useReducer and asyncstorage but not able to achieve that, i have read every article and related questions i am able to do it using useState but did not got the result with useReducer.
Any help/suggestions will be appreciated. Thank You .
const MainScreen = () => {
const getData = async () => {
try {
const data = await AsyncStorage.getItem('itemlist');
return (output = JSON.parse(data));
} catch (e) {
}
};
React.useEffect(() => {
getData();
}, []);
const [text, setText] = React.useState('');// for textinput
const { dispatch } = useContext(NotesContext);
const handleSubmit = async () => {
try {
const output = JSON.stringify(state);
await AsyncStorage.setItem('itemlist', output);
} catch (error) {
console.log(error);
}
if (text) {
dispatch({ type: 'ADD_TODO', payload: text });
}
setText('');
};
//this is my reducer function below
export const TodoReducer = (state, action) => {
switch (action.type) {
case 'ADD_TODO':
return state.concat({
task: action.payload,
id: uuid.v4(),
complete: false,
});
case 'DELETE_TODO':
return state.filter((todo) => todo.id !== action.payload);
default:
throw new Error();
}
};

EXPO-AV not playing sound and not throwing any errors

I am trying to load the sound which i retrieve from my own API into the EXPO AV createAsync function:
const PlayerWidget: React.FC = () => {
const [song, setSong] = useState(null);
const [sound, setSound] = useState<Sound | null>(null);
const [isPlaying, setIsPlaying] = useState<boolean>(true);
const [liked, setLiked] = useState<boolean>(false);
const [duration, setDuration] = useState<number | null>(null);
const [position, setPosition] = useState<number | null>(null);
const { songId } = useContext(AppContext);
const { data, error } = useQuery(SongQuery, {
variables: { _id: songId },
});
useEffect(() => {
if (data && data.song) {
setSong(data.song);
}
}, [data]);
useEffect(() => {
if (song) {
playCurrentSong();
}
}, [song]);
const playCurrentSong = async () => {
if (sound) {
await sound.unloadAsync();
}
const { sound: newSound } = await Sound.createAsync(
{ uri: song.soundUri },
{ shouldPlay: isPlaying }
);
console.log("sound" + newSound);
setSound(newSound);
};
const onPlayPausePress = async () => {
if (!sound) {
console.log("no sound");
return;
}
if (isPlaying) {
await sound.pauseAsync();
} else {
await sound.playAsync();
}
};
const onLikeSong = async () => {
try {
setLiked(true);
} catch (e) {
console.log(e);
}
};
const getProgress = () => {
if (sound === null || duration === null || position === null) {
return 0;
}
return (position / duration) * 100;
};
const onPlaybackStatusUpdate = (status) => {
setIsPlaying(status.isPlaying);
setDuration(status.durationMillis);
setPosition(status.positionMillis);
};
}
Weirdly enough, the log after the function does not even work, it is never logged. I don't get any errors though, making it quite hard to debug this where it goes wrong, the URI is working and pointing towards an mp3 file, and the state is set correctly. Any pointers how i could debug this further?

React Native: No thing show on the screen after getting data from firestore

This is my code:
const [tourists, setTourists] = useState(null)
const [saved,setsave]=useState('');
const {user, logout} = useContext(AuthContext);
const [userData, setUserData] = useState(null);
const [loading, setLoading] = useState(true);
const getUser = async() => {
await firestore()
.collection('users')
.doc( user.uid)
.get()
.then((documentSnapshot) => {
if( documentSnapshot.exists ) {
console.log('User Data in BookMark', documentSnapshot.data());
const list=[];
setUserData(documentSnapshot.data());
console.log('savedPosts: ',documentSnapshot.data().savedPosts);
documentSnapshot.data().savedPosts.map((object, index) => (
firestore().collection('posts').doc(object).get().then((querySnapshot) => {list.push(querySnapshot.data())})
))
setTourists(list);
if (loading) {
setLoading(false);
}
}
})
}
useEffect(() => {
getUser();
}, []);
return (
<View style={{flex: 1, marginTop: Constants.statusBarHeight}}>
{!loading ? ((tourists ||[]).map((object, index) => (...
I have checked through the console and see that firestore worked correctly, I got the data, tourists is not null, but the screen still shows nothing. Can anybody hekp me plz !!!
The issue is in this part:
const list=[];
setUserData(documentSnapshot.data());
console.log('savedPosts: ',documentSnapshot.data().savedPosts);
documentSnapshot.data().savedPosts.map((object, index) => (
firestore().collection('posts').doc(object).get().then((querySnapshot) => {list.push(querySnapshot.data())})
))
setTourists(list);
Becase you use then the setTourists(list) will always save an empty array because then finished after you already set the value. Also a map doesn't support async calls. We need to use a for loop for this.
Change your code to something like this:
const getUser = async () => {
await firestore()
.collection("users")
.doc(user.uid)
.get()
.then(async (documentSnapshot) => {
if (documentSnapshot.exists) {
console.log("User Data in BookMark", documentSnapshot.data());
const list = [];
const posts = [];
setUserData(documentSnapshot.data());
documentSnapshot.data().savedPosts.map((object, index) => {
posts.push(object);
});
for (let i = 0; i < posts.length; i++) {
const post = posts[i];
const docSnapshot = await firestore()
.collection("posts")
.doc(post)
.get();
list.push(docSnapshot.data());
}
setTourists(list);
if (loading) {
setLoading(false);
}
}
});
};

how do I make an array in state - reactnative

I'm taking the images I uploaded to cloud storage, but the problem is the variable is not an array, so it is only storing just one url. How do I make variables with state array?
My code:
const reference = storage().ref('images');
const [imageUrl, setImageUrl] = useState();
const refer = storage().ref('images');
useEffect(() => {
try {
listFilesAndDirectories(reference).then(() => {
console.log('Finished listing');
});
refer.list().then(result => {
result.items.forEach(element => {
element.getDownloadURL().then(downloadUrl => {
setImageUrl(downloadUrl)
console.log(imageUrl)
console.log("=================")
}).catch(error =>{
alert(error)
})
})
})
} catch (error) {
alert(error);
}
}, []);
Is that what you are looking for?
const [items, setItems] = useState([]);
const handleStateChange = () => {
setItems(state => [...state, 'someNewItem']);
}
With useCallback
const handleStateChange = useCallback(function () {
setItems(state => [...state, 'someNewItem']);
}, [])

Getting variable from AsyncStorage and putting into Axios

I have been trying to get a variable from AsyncStorage and then put it into an Axios get request. The problem is that the variable is not updating to the data that is retrieved from AsyncStorage. How do I make it do that?
Here is my code:
const [sku, setSku] = useState('')
const STORAGE_KEY_SKU = '#save_sku'
const readSku = async () => {
try {
const selectedSku = await AsyncStorage.getItem(STORAGE_KEY_SKU)
if (selectedSku !== null) {
setSku(selectedSku)
}
} catch (e) {
alert('Failed to fetch the data from storage')
}
}
useEffect(() => {
readSku()
}, []);
useEffect(() => {
Axios.get(`https://api.vexdb.io/v1/get_matches?sku=${sku}`)
.then(({ data }) => {
//console.log("defaultApp -> data", data)
setData(data.result)
})
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
Im trying to put get the sku variable from the state from AsyncStorage, but the ${sku} in the axios get request link is not working, the sku is blank in that statement.
Please help, thanks!
useFocusEffect(() => {
readSku()
}, []);
const STORAGE_KEY_SKU = '#save_sku'
// to get the session username from localstorage
const readSku = async () => {
try {
const selectedSku = await AsyncStorage.getItem(STORAGE_KEY_SKU)
if (selectedSku !== null) {
setSku(selectedSku)
}
} catch (e) {
console.log(e);
}
}
const setSku = async (selectedSku) => {
Axios.get(`https://api.vexdb.io/v1/get_matches?sku=${selectedSku}`)
.then(({ data }) => {
//console.log("defaultApp -> data", data)
setData(data.result)
})
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}