Reputation: 184
I am trying to get a better understanding of redux and react lifecycle method.
I have a prop function on component did mount that calls a function in redux. On redux I am calling the location to get the position and setting the initial state and updating it when the call gets made. I am able to get the position but no matter what I've tried through redux, my coords(initial state) still comes out as undefined. I tried a .then() on the componentDidMount function and set state locally and this worked. But I would like to use this feature with redux to try and get a better understanding of it. My understanding is that as long as there is an initial state, there should not be a problem in updating it. But I feel that my problem may be somewhere with my action.payload. As it is not logging anything in my switch case for GET_LOCATION. One thing of note, i get a yellow warning on my console, '[Violation] Only request geolocation information in response to a user gesture.' I am not sure if this impacts anything. Anyways, any suggestions would be vastly appreciated. I've searched high and low for a nice solution to geolocation through redux. Here is the code:
const initialState = {
coords: { }
};
export function getLocation() {
const geolocation = navigator.geolocation;
return {
type: GET_LOCATION,
payload: geolocation.getCurrentPosition((position) => {
console.log(position.coords)
return position
})
}
};
Switch Statement:
case GET_LOCATION:
console.log(GET_LOCATION)
return Object.assign({},
state,
{
coords: action.payload
}
)
Upvotes: 2
Views: 3852
Reputation: 43
Had similar issue, even though I could console.log the coordinates within the promise success case, I wasn't able to get the state to update. You need to nest the promise inside a function in the action creator. This allows you to call the dispatch function within the resolve case, dispatching the data to the reducers with the data asynchronously. See below:
export const location = () => {
return function (dispatch) {
return new Promise((resolve, reject) => {
if (!navigator.geolocation) {
reject(new Error('Not Supported'));
}
navigator.geolocation.getCurrentPosition((position) => {
var action = {
type: FETCH_LOCATION,
payload: {
lat: position.coords.latitude,
long: position.coords.longitude,
time: position.timestamp
}
}
resolve(position);
dispatch(action)
}, () => {
reject(new Error('Permission denied'));
});
});
}
};
Upvotes: 1
Reputation: 1067
geolocation.getCurrentPosition
is asynchronous, so it's not returning anything to put in payload.
You need to use redux-thunk to dispatch asynchronously. Follow the instructions to set it up if you've never used it, then you should be able to change your action creator like this:
export function getLocation() {
return dispatch => {
const geolocation = navigator.geolocation;
geolocation.getCurrentPosition((position) => {
console.log(position.coords);
dispatch({
type: GET_LOCATION,
payload: position
});
});
};
Upvotes: 7