Search code examples
react-nativereduxreact-reduxexpo

ERROR Error: Actions must be plain objects. Instead, the actual type was: 'undefined'


I am trying to access user location when they click on a button but I keep getting an error,

ERROR Error: Actions must be plain objects. Instead, the actual type was: 'undefined'. You may need to add middleware to your store setup to handle dispatching other values, such as 'redux-thunk' to handle dispatching functions. i went through react redux and found out about react redux handling asynchronous function, so I went to add thunk on my project store but am still getting tesame error

here is my code

//store.js file

import { userSlice } from './slices/userSlice';
import { homeSlice } from './slices/HomeSlice';
import thunk from 'redux-thunk';
// import thunkMiddleware from 'redux-thunk';

const rootReducer = combineReducers({
    user: userSlice.reducer,
    home: homeSlice.reducer,
});

const store = configureStore({
    reducer: rootReducer,
    middleware: (getDefaultMiddleware) =>
        getDefaultMiddleware().concat(thunk),
});

export default store;

//userslice.js


const initialState = {
    userLocation: null,
}

export const userSlice = createSlice({
    name: 'user',
    initialState,
    reducers: {
        
        setUserLocation: (state, action) => {
            state.userLocation = action.payload
        },
    },
})

// Action creators are generated for each case reducer function
export const { setUserLocation,} = userSlice.actions

export const selectUserLocation = (state) => state.user.userLocation

export default userSlice.reducer
import { SafeAreaView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { selectSearchMode } from '../slices/HomeSlice';
import { selectUserLocation, setUserLocation } from '../slices/userSlice';
import FlatButton from '../component/FlatButton';
import SearchComponent from '../component/for_user/SearchComponent';
import tw from 'twrnc';
import * as Location from 'expo-location';

const LocationCheckerScreen = () => {
    const [locationPermission, setLocationPermission] = useState(false);
    const [userLocation, setUserLocation] = useState(null);
    const selectSearchMod = useSelector(selectSearchMode);
    const selectLocationChecker = useSelector(selectUserLocation);
    const dispatch = useDispatch();

    const handleLocation = (location) => {
        if (location === null || location === undefined) {
            dispatch(setUserLocation({ location: null }));
        } else {
            dispatch(setUserLocation({ location }));
        }
    };

    const setCurrentLocation = async () => {
        try {
            let { status } = await Location.requestForegroundPermissionsAsync();

            if (status !== 'granted') {
                console.log('Permission to access location was denied');
                return;
            }

            let location = await Location.getCurrentPositionAsync({});
            if (location){
                setUserLocation(location)
            }
        } catch (error) {
            console.log('Error occurred while getting location:', error);
        }
    };

    useEffect(() => {
        setCurrentLocation();
    }, []);

    useEffect(() => {
        if (userLocation && userLocation !== "later") {
            handleLocation(userLocation);
        }
    }, [userLocation]); 

    return (
        <SafeAreaView style={tw`px-4 flex-1 pb-4`}>
            {selectLocationChecker === null ? (
                <View style={tw`px-4 justify-center`}>
                    <View style={tw`my-6`}>
                        <Text style={tw`text-xl mb-3 font-semibold text-center`}>Where is your present location?</Text>
                        <Text style={tw`text-[14px] text-center`}>
                            Let us help the employer easily find your location and ensure a smooth and efficient process in locating
                            you.
                        </Text>
                    </View>
                    <View style={tw`px-5 mt-3`}>
                        <FlatButton text="Set location automatically" onPress={() => setCurrentLocation()} />
                        <TouchableOpacity
                            style={tw`flex-row justify-center p-[6px] mt-3 border-2 border-gray-500 rounded-lg hover:bg-gray-300`}
                            onPress={() => handleLocation('later')}
                        >
                            <Text style={tw`text-lg font-semibold`}>Set later</Text>
                        </TouchableOpacity>
                    </View>
                </View>
            ) : (
                <View style={tw`px-6 flex-1`}>
                    <SearchComponent />
                </View>
            )}
        </SafeAreaView>
    );
};

export default LocationCheckerScreen;

const styles = StyleSheet.create({});

Solution

  • I think that because your state setter is the same name as the action. this is your action

    export const { setUserLocation,} = userSlice.actions
    

    inside LocationCheckerScreen you have this useState

    const [userLocation, setUserLocation] = useState(null);
    

    when you dispatch, i think you are dispatching useState setter

    if (location === null || location === undefined) {
            dispatch(setUserLocation({ location: null }));
    

    change the name of the useState setter