Augustin Riedinger
Augustin Riedinger

Reputation: 22148

Automatically add the current user's geolocation

I'm still new to Redux.

I want my app to manage a list of places. I have followed the Official TODOList tutorial and replaced TODOs with Places. Good start :)

Now, I'd like to use the Geolocation API to automatically add the current user's place if available.

I have a <PlaceInput> container, which when triggered dispatches the event addPlace.

But I'm wondering where I should add the logic to add the current users' place.

1. At the root document?

let store = createStore(placesApp);

// update the store immediately if available

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

I'm not a big fan of this strategy since the authorization for geolocation requires user action the first time, which makes it asynchronous by nature.

2. In a "fake" container that does just this?

class AddUserGeolocation extends React.Component {

  static propTypes = {
    alreadyAsked: React.PropTypes.bool.isRequired
  }

  componentDidMount {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition((position) => {
        dispatcher(addPlace('You', position.coords.latitude, position.coords.longitude))
      });
      dispatcher(askedForUserLocation())
    }
  };

  render() {
    let result = this.props.alreadyAsked ? 'Asked' : 'Not yet'
    return (
      <div>
        {result}
      </div>
    )
  }
}

Upvotes: 3

Views: 874

Answers (1)

Michael Rasoahaingo
Michael Rasoahaingo

Reputation: 1089

You can store this information in the Store. :D All the logic is handled inside your reducer. Something like this:

const initialState = {
    places: [],
    alreadyAsked: false
};

const placesReducer = (state = [], action) => {
    switch(action.type) {
        case 'ADD_PLACE':
            return [...state, action.place];
        default:
            return state;
    }
};

const askReducer = (state = false, action) => {
    switch(action.type) {
        case 'ASK':
            return true;
        default:
            return state;
    }
};

const appReducers = combineReducers({
    places: placesReducer,
    alreadyAsked: askReducer
});

let store = createStore(initialState, appReducers);

// update the store immediately if available

render(
        <Provider store={store}>
            <App />
        </Provider>,
        document.getElementById('root')
);

And

@connect(
    state => ({
        places: state.places,
        alreadyAsked: state.alreadyAsked
    }),
    dispatcher => ({
        addPlace: (who, lat, long) => ({ type: 'ADD_PLACE', {who, lat, long}}),
        askedForUserLocation: () => ({ type: 'ASK' })
    })
)
class AddUserGeolocation extends React.Component {

    static propTypes = {
        alreadyAsked: React.PropTypes.bool.isRequired
    }

    componentDidMount() {
        const { addPlace, askedForUserLocation } = this.props

        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition((position) => {
                dispatcher(addPlace('You', position.coords.latitude, position.coords.longitude))
            });
            dispatcher(askedForUserLocation())
        }
    }

    render() {
        let result = this.props.alreadyAsked ? 'Asked' : 'Not yet'
        return (
            <div>
                {result}
            </div>
        )
    }
}

Upvotes: 1

Related Questions