New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Have any suggestions for where to put something like an Esri or Leaflet Map object in Flux architecture? #1279

Closed
Robert-W opened this Issue Jan 25, 2016 · 9 comments

Comments

4 participants
@Robert-W

Do you have any suggestions for how to handle a mutable map object that manages it's own state and controls it's own rendering (to canvas or appending images as map layers) in a flux architecture? I know you require your stores to be essentially immutable which is why I am not sure where to put this.

Typically where I work we build our UI in React and use Flux to model our UI state (currently using Alt but I want to switch to Redux). We are however primarily an Esri shop so almost all of our applications use Esri's JSAPI and we frequently have to interact with the map object to add/remove/show/hide layers/graphics, apply definitions, do queries, etc.

We have come up with two approaches but was curious what you guys think or if you know of a better approach.

One method is to put the map object in the store, and then make changes to it using esri's api and route all of our functionality through actions, so we can emit change events anytime we interact with it and then derive our UI state from this map object. However we are just storing a reference to the map in the store and mutating it every time(we can't not mutate it because of how their api works) and this can get complex because not all UI can be derived directly from the map easily. It often requires parsing strings from arrays or deeply nested json objects which can be error prone.

The other method we have used is to store the map in the global scope under an app variable and take it out of flux completely. We then store a minimal amount of information about the map in the stores, just enough so we can render the UI (so things like which layers are visible and the state of their controls). We then interact with the map object after the store changes using the functions that are subscribed to the store. This way the store is immutable but we are duplicating a little bit of data.

@sompylasar

This comment has been minimized.

Show comment
Hide comment
@sompylasar

sompylasar Jan 26, 2016

  1. You should not put non-plain objects to the Redux state store -- it should be serializable.
  2. You can put essential map state, like marker placement, layer on-off state etc. into the Redux state store.
  3. You should wrap your map JSAPI component into a React component to do rendering the React-way, having props declaring the desired UI state, and having the component to determine the set of map JSAPI calls to change the map UI from its current state to the desired state obtained from props
  4. You should connect the component to Redux state store to map the state to its props.
  1. You should not put non-plain objects to the Redux state store -- it should be serializable.
  2. You can put essential map state, like marker placement, layer on-off state etc. into the Redux state store.
  3. You should wrap your map JSAPI component into a React component to do rendering the React-way, having props declaring the desired UI state, and having the component to determine the set of map JSAPI calls to change the map UI from its current state to the desired state obtained from props
  4. You should connect the component to Redux state store to map the state to its props.
@Robert-W

This comment has been minimized.

Show comment
Hide comment
@Robert-W

Robert-W Jan 26, 2016

Hmm interesting.

So if I have an App component. I should map my essential map state to props and pass it to the Map component. Then in the Map I would translate the received props to API calls or pass those further down to the map controls so they could render correctly?

Then would the reference to the map live in the map component? The JSAPI map is a Dojo dijit unfortunately so typically we render a div in our Map component and then after the component mounts, we call something like app.map = new Map('map', mapOptions); but we want to get away from putting it in a global variable.

Hmm interesting.

So if I have an App component. I should map my essential map state to props and pass it to the Map component. Then in the Map I would translate the received props to API calls or pass those further down to the map controls so they could render correctly?

Then would the reference to the map live in the map component? The JSAPI map is a Dojo dijit unfortunately so typically we render a div in our Map component and then after the component mounts, we call something like app.map = new Map('map', mapOptions); but we want to get away from putting it in a global variable.

@Robert-W

This comment has been minimized.

Show comment
Hide comment
@Robert-W

Robert-W Jan 26, 2016

Sorry if this is the wrong place for this, seems like more of a general Flux question, but since we are considering switching from Alt.js to Redux I figured I would ask here to see if redux had any helpers for this kind of thing (like the mapStateToProps).

Sorry if this is the wrong place for this, seems like more of a general Flux question, but since we are considering switching from Alt.js to Redux I figured I would ask here to see if redux had any helpers for this kind of thing (like the mapStateToProps).

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Jan 26, 2016

Collaborator

I’ll close this as a duplicate of https://github.com/rackt/redux/issues/606.

Collaborator

gaearon commented Jan 26, 2016

I’ll close this as a duplicate of https://github.com/rackt/redux/issues/606.

@gaearon gaearon closed this Jan 26, 2016

@Robert-W

This comment has been minimized.

Show comment
Hide comment

thanks @gaearon

@markerikson

This comment has been minimized.

Show comment
Hide comment
@markerikson

markerikson Jan 26, 2016

Contributor

@Robert-W : you may want to take a look at https://github.com/lelandrichardson/react-native-maps and https://github.com/uber/react-map-gl. Those both appear to be good implementations of React components wrapping JS map libraries.

Contributor

markerikson commented Jan 26, 2016

@Robert-W : you may want to take a look at https://github.com/lelandrichardson/react-native-maps and https://github.com/uber/react-map-gl. Those both appear to be good implementations of React components wrapping JS map libraries.

@Robert-W

This comment has been minimized.

Show comment
Hide comment
@Robert-W

Robert-W Jan 26, 2016

thanks @markerikson

I will check out their implementation. Looks promising, most examples I have seen just load a map and call it the quits, so it's nice to see one a little less trivial.

thanks @markerikson

I will check out their implementation. Looks promising, most examples I have seen just load a map and call it the quits, so it's nice to see one a little less trivial.

@sompylasar

This comment has been minimized.

Show comment
Hide comment
@sompylasar

sompylasar Jan 26, 2016

Then would the reference to the map live in the map component? The JSAPI map is a Dojo dijit unfortunately so typically we render a div in our Map component and then after the component mounts, we call something like app.map = new Map('map', mapOptions); but we want to get away from putting it in a global variable.

Yes. I don't know Dojo specifics, but generally you would store a reference to your map JSAPI object right on the React Map component, and you would initialize the map JSAPI object with a React div's "ref" to the browser DOM element, not with a string identifier.

Then would the reference to the map live in the map component? The JSAPI map is a Dojo dijit unfortunately so typically we render a div in our Map component and then after the component mounts, we call something like app.map = new Map('map', mapOptions); but we want to get away from putting it in a global variable.

Yes. I don't know Dojo specifics, but generally you would store a reference to your map JSAPI object right on the React Map component, and you would initialize the map JSAPI object with a React div's "ref" to the browser DOM element, not with a string identifier.

@Robert-W

This comment has been minimized.

Show comment
Hide comment
@Robert-W

Robert-W Jan 26, 2016

Sounds good to me, I will try that out. Thanks

Sounds good to me, I will try that out. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment