I`m trying to implement a switch that can be switched on and off and according to the state a different image and text is shown. With the help of a tutorial I did the following:
First I created store.js:
import { configureStore } from '@reduxjs/toolkit';
import switchReducer from './switch';
export const store = configureStore({
reducer: {
switchVal: switchReducer
}
});
Then I created switch.js
import { createSlice } from '@reduxjs/toolkit';
const switchSlice = createSlice({
name: 'alarm',
initialState: {
active: true
},
reducers: {
toggleSwitch: (state) => {
state.active = !state.active;
},
}
});
export const toggleSwitch = switchSlice.actions.toggleSwitch;
export default switchSlice.reducer;
In App.js I imported {store} and wrapped around my BottomTab Navigator.
Now the switch is in Alarm.js which looks like this:
import React from 'react';
import { StyleSheet, Text, View, Image, ScrollView, Pressable, Switch } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import { globalStyles } from '../components/globalStyles';
import { toggleSwitch } from '../components/switch';
function Alarm({navigation}) {
const switchValue = useSelector((state) => state.switchValue);
const dispatch = useDispatch();
const alarmEnabled = require('../images/Alarm_enabled.png');
const alarmDisabled = require('../images/Alarm_disabled.png');
function toggleSwitchHandler() {
if (switchValue == true) {
dispatch(toggleSwitch(value));
} else {
dispatch(toggleSwitch(value));
}
}
return (
<ScrollView>
<View style={globalStyles.containerBodyAlarm}>
<View style={globalStyles.containerMainAlarm}>
<View style={globalStyles.containerImageAlarm}>
<Image style={{ width: 130, height: 130, resizeMode: 'contain', marginTop: 20, marginBottom: 10}} source={switchValue ? alarmDisabled : alarmEnabled } />
</View>
<View style={globalStyles.containerButtonAlarm}>
<Text style={globalStyles.textButtonAlarm}>{switchValue ? 'Alarm is deactivated' : 'Alarm is activated'}</Text>
<Switch
trackColor={{false: '#919190', true: '#000099'}}
thumbColor={'#5E5E5D'}
value={switchValue}
onValueChange= {toggleSwitchHandler}
/>
<Text style={globalStyles.textButtonAlarm2}>{switchValue ? 'activate' : 'deactivate'}</Text>
</View>
</View>
</View>
</ScrollView>
);
}
export default Alarm;
const styles = StyleSheet.create({
pressed: {
opacity: 0.7,
},
Unfortunately it's not working. What am I doing wrong? I'm sorry for the bad coding, I'm not good at it.
CodePudding user response:
Your initial state looks like:
initialState: {
active: true
},
However, you are getting the value by doing:
const switchValue = useSelector((state) => state.switchValue);
That does not exist, it needs to be:
const switchValue = useSelector((state) => state.active);
function toggleSwitchHandler() {
if (switchValue == true) {
dispatch(toggleSwitch(value));
} else {
dispatch(toggleSwitch(value));
}
}
The if
here has no use since both callers have the same props.
Also, value
does not exist, since you're flipping the boolean inside the reducer, no need for the param.
Change it to:
function toggleSwitchHandler() {
dispatch(toggleSwitch());
}
To invert the current boolean
CodePudding user response:
you can make 2 reducers, one with value true the other with value false
import { createSlice } from '@reduxjs/toolkit';
const switchSlice = createSlice({
name: 'alarm',
initialState: {
active: true
},
reducers: {
toggleOn: (state) => {
state.active = true;
},
toggleOff: (state) => {
state.active = false;
}
}
});
export const {toggleOn, toggleOff} = switchSlice.actions;
export default switchSlice.reducer;
get the value of toggle
const switchValue = useSelector((state) => state.alarm.active);
use it
function toggleSwitchHandler() {
if (switchValue == true) {
dispatch(toggleOff());
} else {
dispatch(toggleOn());
}
}