I am using NextJs as a SSR for React application. I want to find the geolocation of the user when the page first load. I am trying to use react-redux, redux and redux-thunk to maintain the location.

But:

  1. The redux store is not able to dispatch the location(lat,long) .
  2. The action function, i.e., function to find the location (getLocation in my case) when I place this function in componentWillMount() it gives error:

navigator is not defined.

I am following this example: codepen link

redux/actions/locationActions.js

import { GET_LOCATION } from "../types";

const getLocation = () => {
  const geolocation = navigator.geolocation;

  const location = new Promise((resolve, reject) => {
    if (!geolocation) {
      reject(new Error("Not Supported"));
    }

    geolocation.getCurrentPosition(
      position => {
        resolve(position);
      },
      () => {
        reject(new Error("Permission denied"));
      }
    );
  });

  return {
    type: GET_LOCATION,
    payload: location
  };
};

export default {
  getLocation
};

redux/actions/index.js

import locationActions from "./locationActions";

export default {
  ...locationActions
};

redux/reducers/locationReducer.js

import { GET_LOCATION } from "../types";

const initialState = {
  coords: {
    latitude: 0,
    longitude: 0
  }
};

export default (state = initialState, action) => {
  switch (action.type) {
    case GET_LOCATION:
      return { location: action.payload };
    default:
      return state;
  }
};

redux/reducers/index.js

import { combineReducers } from "redux";
import locationReducer from "./locationReducer";

const rootReducer = combineReducers({
  location: locationReducer
});

export default rootReducer;

redux/index.js

import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import reducer from "./reducers";

export const initStore = (initialState = {}) => {
  return createStore(reducer, initialState, applyMiddleware(thunk));
};

pages/_app.js

import React from "react";
import App, { Container } from "next/app";
import Head from "next/head";
import { Provider } from "react-redux";
import withRedux from "next-redux-wrapper";
import { initStore } from "../redux";
import "@fortawesome/fontawesome-free/css/all.min.css";
import "bootstrap-css-only/css/bootstrap.min.css";
import "mdbreact/dist/css/mdb.css";
import StyleHeader from "../components/StyleHeader";

export default withRedux(initStore, { debug: true })(
  class MyApp extends App {
    static async getInitialProps({ Component, ctx }) {
      return {
        pageProps: {
          ...(Component.getInitialProps
            ? await Component.getInitialProps(ctx)
            : {})
        }
      };
    }

    render() {
      const { Component, pageProps, store } = this.props;
      return (
        <Container>
          <Provider store={store}>
            <StyleHeader />
            <Component {...pageProps} />
          </Provider>
        </Container>
      );
    }
  }
);

pages/index.js

import Link from "next/link";
import React from "react";
import { connect } from "react-redux";
import { MDBBtn, MDBCol, MDBContainer, MDBRow } from "mdbreact";
import Layout from "../components/Layout";
import Home from "../components/Home/Home";
import actions from "../redux/actions";

class Index extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    this.props.getLocation();
  }

  render() {
    return (
      <Layout>
        <Home />
      </Layout>
    );
  }
}

const mapStateToProps = state => {
  return { location: state.location };
};

export default connect(
  mapStateToProps,
  actions
)(Index);

What is exactly I am doing wrong?

Thanks in advance.

0 Answers