Home > front end >  How to toggle an on/off switch with redux toolkit?
How to toggle an on/off switch with redux toolkit?

Time:04-30

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());
   }
}
  • Related