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

huangapple go评论52阅读模式
英文:

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({});
英文:

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 &#39;./slices/userSlice&#39;;
import { homeSlice } from &#39;./slices/HomeSlice&#39;;
import thunk from &#39;redux-thunk&#39;;
// import thunkMiddleware from &#39;redux-thunk&#39;;

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

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

export default store;

//userslice.js


const initialState = {
    userLocation: null,
}

export const userSlice = createSlice({
    name: &#39;user&#39;,
    initialState,
    reducers: {
        
        setUserLocation: (state, action) =&gt; {
            state.userLocation = action.payload
        },
    },
})

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

export const selectUserLocation = (state) =&gt; state.user.userLocation

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

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

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

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

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

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

    useEffect(() =&gt; {
        setCurrentLocation();
    }, []);

    useEffect(() =&gt; {
        if (userLocation &amp;&amp; userLocation !== &quot;later&quot;) {
            handleLocation(userLocation);
        }
    }, [userLocation]); 

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

export default LocationCheckerScreen;

const styles = StyleSheet.create({});

答案1

得分: 3

我认为是因为你的状态设置器与动作同名。这是你的动作。

LocationCheckerScreen 中,你有这个 useState

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

当你派发时,我认为你正在派发 useState 的设置器:

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

改变 `useState` 设置器的名称


<details>
<summary>英文:</summary>

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




</details>



huangapple
  • 本文由 发表于 2023年5月21日 09:00:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76297890.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定