英文:
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 './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({});
答案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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论