how to save toggle button prefrence in localstorage - javascript

i have a togle button which uses useTimeoutPoll plugin to fetch some data in 10 seconds intervals, i want to save the state of this togle button to local storage but i cant figure out how to do it, please if anyone can help. this is the code below
const fetchData = async () => {
await data.loadUpdate(id)
}
const { isActive, pause, resume } = useTimeoutPoll(fetchData, 10000)
const toggleUpdate = computed(() => {
if (isActive) {
return resume
} else return pause
})
and i use the togle like this
<Toggle
v-model="isActive"
#click="toggleUpdate"
>
<span>
update
</span>
</Toggle>

localStorage save item
localStorage.setItem(key, value)
localStorage take item
localStorage.getItem(key)
localStorage remove item
localStorage.removeItem(key)
Here is an example of how you can do it:
const toggleUpdate = computed(() => {
localStorage.setItem('isActive', isActive)
if (isActive) {
return resume
} else return pause
})
I hope it helps.

Related

Stop setInterval function set inside useEffect

I have this simple useEffect code. When the user logged in to the application every 2 minutes I will dispatch an action which is an API call, and I need to stop this interval once a user is logged out. Still, the current code even runs after the user is logged out, what shall I do to prevent this interval when the user logs out.
I am using the value from the localStorage to determine whether the user is logged in or not.
const intervalId = useRef(null)
useEffect(() => {
const isLoggedIn = localStorage.getItem("isUserLoggedIn") //(true or false)
intervalId.current = setInterval(() => {
dispatch(refreshUserToken());
if(isLoggedIn === false){
clearInterval(intervalId.current)
}
},1000*60*2)
return () => {
clearInterval(intervalId.current)
}
},[])
Is there any way to resolve my issue?
Any help would be much appreciated!!
You should be adding the line where you get that value from localStorage inside the interval, if you want the updated value. Also, localStorage would gives you a string instead of a boolean, either you parse it, or you change your if statement. Try with this:
const intervalId = useRef(null);
useEffect(() => {
intervalId.current = setInterval(() => {
const isLoggedIn = localStorage.getItem("isUserLoggedIn"); //(true or false)
if (isLoggedIn === "false") {
clearInterval(intervalId.current);
return;
}
dispatch(refreshUserToken());
}, 1000 * 60 * 2);
return () => {
clearInterval(intervalId.current);
};
}, []);
You could use an event instead of a setInterval. As an example, change the code where you are setting the localStorage to this:
localStorage.setItem("isUserLoggedIn", true); // or false depending on the context
window.dispatchEvent(new Event("storage")); // you notice that there is a change
You change your useEffect to this:
useEffect(()=>{
const listenStorageChange = () => {
const isLoggedIn = localStorage.getItem("isUserLoggedIn");
console.log(isLoggedIn);
// do your logic here
};
window.addEventListener("storage", listenStorageChange);
return () => window.removeEventListener("storage", listenStorageChange);
},[])
The keys and the values stored with localStorage are always in the UTF-16 string format. As with objects, integer keys and booleans are automatically converted to strings.
So you have to call like this:
if(isLoggedIn === 'false'){
clearInterval(intervalId.current)
}
Check the documentation.

Tracking changes in state?

The component code has several parameters, each of which has an initial value received from the server. How can I track that one of them (or several at once) has changed its state from the original one in order to suggest that the user save the changes or reset them?
Something similar can be seen in Discord when changing the profile / server.
The solution I found using useEffect () looks redundant, because there may be many times more options.
const [hiddenData, setHiddenData] = useState(server.hidden_data);
const [hiddenProfile, setHiddenProfile] = useState(server.hidden_profile);
const [isChanged, setIsChanged] = useState(false);
useEffect(() => {
if (hiddenData !== server.hidden_data
|| hiddenProfile !== server.hidden_profile) {
setIsChanged(true);
} else {
setIsChanged(false);
}
}, [hiddenData, server.hidden_data, hiddenProfile, server.hidden_profile]);
return (
<>
{isChanged && <div>You have unsaved changes!</div>}
</>
);
Maybe something like that?
const [draftState, setDraftState] = useState(server)
const [state, setState] = useState(server)
// a more complex object with the list of changed props is fine too
const isChanged = lodash.isEqual(state, draftState)
function changeProp (prop, value) {
setState({
...draftState,
[prop]: value
})
}
function saveState () {
setState(draftState)
// Persist state if needed
}

Troubles using AsyncStorage

Im developing a simple app and i need to save a couple of user data so im using AsyncStorage like that:
const storeAge = async (age) => {
try {
console.log("STORED age: " + age);
await AsyncStorage.setItem("#age", age);
} catch (e) {
// saving error
}
};
And im calling this function here:
<SetupInfo
visible={isStartUp}
onRegist={registHandler}
onRegistDataSave={storeAge}
/>
The onRegistDataSave is called on a press of a button on the SetupInfo component:
const addRegistHandlerMemory = () => {
if (!isEnabled) {
props.onRegistDataSave(age / 12);
} else {
props.onRegistDataSave(age);
}
setAge("");
};
...
<Button
title="REGIST"
onPress={() => {
addRegistHandler();
addRegistHandlerMemory();
}}
style={styles.button}
/>
The console.log on store.age is showing the correct input when button is pressed, but when i reload the app and call this:
const getAge = async () => {
try {
const value = await AsyncStorage.getItem("#age");
if (value !== null) {
console.log("valor" + value)
setAppMode(false);
setAge(parseFloat(value));
}
console.log("age " + value);
} catch (e) {
// error reading value
}
};
the value I got is null, why is this happening?
(Well i think i know becouse im doing the same think to save data on one array and the last value is not saved which means that probably is saving on the next render that for me - a noob on this- doent make sense since the set age is an async funtion that should avoid that...)
Oh I figure it out where the error was. Turns out I was saving a number and AsyncStorage just saves Strings, so i just need to add const string = toString(age); on storeAge and save that value.

Using axios doesn't rerender my React Native component

I am using hooks in React Native. This is my code:
useEffect(() => {
if (var1.length > 0 ){
let sym = [];
var1.map((items) => {
let count = 0;
state.map((stateItems) => {
if(items === stateItems.name) {
count = count + 1;
}
})
if (count === 0) {
sym.push(items)
}
});
async function getAllStates (sym) {
let stateValues = [];
await Promise.all(sym.map(obj =>
axios.get(ServerURL + "/note?name=" + obj).then(response => {
stateValues.push(response.data[0]);
})
)).then(() =>{
setNewItem(stateValues);
});
}
getAllStates (sym);
}
}, [var1]);
useEffect(() => {
let stateValues = state;
for( let count = 0 ; count < newItem.length; count++ ){
stateValues.push(newItem[count]);
}
setState(stateValues);
}, [newItem]);
This runs successfully without any errors. However, when the state is displayed as below, I am not seeing the latest value added in the state. It shows all the previous values. When I refresh the whole application, I am able to see my value added.
return (
<View style={styles.container}>
<Text style = {{color:"white"}}>
{
state.map( (item, key) =>{
return(
<Text key = {key} style = {{color:"white"}}> {item.name} </Text>
)
})
}
</Text>
</View>
);
Can someone tell me why this is happening? I want to see the data render immediately after the axios call. I am using React Native.
when i force update using :stackoverflow.com/questions/53215285/... it works fine. However, i am looking for a better fix if anyone can provide?
This should do:
useEffect(() => {
var1.forEach(async (name) => {
if (state.some(item => item.name === name)) return;
const response = await axios.get(ServerURL + "/note?name=" + name);
setState(state => [...state, response.data[0]]);
});
}, [var1]);
I still see two issues in your approach:
this code may start the same ajax request multiple times before the result of the firstz ajax-request is added to state; this also means that the result for the same name may be added multiple times to state.
for each item of var1 times each item of state, this is an O(n*m) problem or in this case basically O(n²) as m is pretty fast catching up to n. You should find a better approach here.
And I'm almost certain that [var1] is wrong here as the dependency for useEffect. But you'd need to show where this value comes from to fix that, too.

Push function is not working properly localStorage Javascript vanilla

I am doing a time-to-click game as you can imagine the fastest time would be the first place. I just want to have 3 scores. and have it on localstorage but every time I start a new game the actual score resets its value and it doesnt generate other scores. the 3 scores should have as value 0. I tried to push them as arrays but push function is not working well. at this point I am stuck. I dont know what to do. If u may help me, I would be really grateful, thanks!
let times = Array.from({
length: 3
})
let interval2;
// Timer CountUp
const timerCountUp = () => {
let times = 0;
let current = times;
interval2 = setInterval(() => {
times = current++
saveTimes(times)
return times
}, 1000);
}
// Saves the times to localStorage
const saveTimes = (times) => {
localStorage.setItem('times', JSON.stringify(times))
}
// Read existing notes from localStorage
const getSavedNotes = () => {
const timesJSON = localStorage.getItem('times')
try {
return timesJSON ? JSON.parse(timesJSON) : []
} catch (e) {
return []
}
}
//Button which starts the countUp
start.addEventListener('click', () => {
timerCountUp();
})
// Button which stops the countUp
document.querySelector('#start_button').addEventListener('click', (e) => {
console.log('click');
times.push(score = interval2)
getSavedTimes()
if (interval) {
clearInterval(interval);
clearInterval(interval2);
}
})
This:
// Button which stops the countUp
document.querySelector('#start_button').addEventListener('click', (e) => {
Probably should be this:
// Button which stops the countUp
document.querySelector('#stop_button').addEventListener('click', (e) => {
...considering you're already attaching an event-handler to start's 'click' event in the previous statement, and no-one would use #start_button as the id="" of a stop button.

Categories