I am trying to create a button that when i click it it will be disabled and when i reload the app it will stay disabled , until i press clear.
The problem is i have to click twice to get the result i want. Here is my code:
github.com/giannischiout/stateBtn/tree/master
import React, {useState, useEffect} from 'react';
import {
View,
TouchableOpacity,
Button,
Text,
} from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
export const BtnSave = () => {
const [isChecked, setIsChecked] = useState(false);
useEffect(() => { getButtonOption() }, [])
const getButtonOption = async () => {
try {
const jsonValue = await AsyncStorage.getItem('buttonCheck', )
const value = JSON.parse(jsonValue)
setIsChecked(value);
} catch(e) {
console.log(e)
}
}
//Execute when i click the button
const buttonActions = async () => {
setIsChecked(previousValue => !previousValue)
buttonSaveClicked();
};
const buttonSaveClicked = async () => {
let btnValue = isChecked.toString();
//Have to click twice to change the value
console.log(`btn value is: ${btnValue}`)
await AsyncStorage.setItem('buttonCheck',btnValue )
};
return (
<TouchableOpacity >
<View>
<Button title='save settings' onPress={buttonActions}></Button>
</View>
</TouchableOpacity>
)
}
2
Answers
The problem is with the getButtonOption function, since the key does not exist yet in the asyncstorage, it returns a null. Hence your isChecked is null on the first press. A very simple fix is to check if the value that is being retrieved on first load is a null value or not. Then set the correct state from there.
I’m not sure if I totally understood your question but I can see some improvements that could help you and maybe it’ll solve what you want.
Not parsing correctly the received JSON
I noticed that your function from parsing isn’t considering the value as
Boolean
and you are trying to set a string'true'
or'false'
(string) to the valueisChecked
, that you expect to betrue
orfalse
(booleans).Remember that if you expect a boolean value and pass a non-empty string to it, it’ll always evaluate
true
!A simple change could fix that when saving:
No
await
ing inside yourbuttonActions()
functionI also noticed that you forgot to
await
the response frombuttonSaveClicked()
inside yourbuttonActions()
function. I think changing the value fromAsyncStorage
inside this callback is a bad practice and provided one approach that I consider better later at this same response.Calling an
async
function insideuseEffect()
from outside contextIf you want to call an
async
function inside auseEffect()
callback, make that function inside of theuseEffect()
callback such as (this article has some context about it):Reactively calling
AsyncStorage.setItem()
inside anotheruseEffect()
You could take advantage of the reactive behavior of ReactJS and change the AsyncStorage value when the local state is changed, inside another
useEffect()
hook directly. Something like this could work:I hope this could help you to solve your code!