Redux for use in mapping applications - reactjs

I know that redux is great for handling the global state of an application, and when that state is updated to reflect that in the view. However, is it possible to use it on a react component that shouldn't re-render? I have a map which uses leaflet and rather than re-render and plot the data, I want it to plot the data without re-rendering.
Does redux seem like a good choice? If so, where would I handle api calls as I was told it should not be done in the reducer.
Currently my app consists of a nav bar, a fullscreen map and a search menu which is populated from an api request. The idea is that when a search is selected it populates data onto the map.

Can you share how you're using Leaflet and React without Redux?
Essentially, React components will always re-render if their state changes, so you can either have a React component that updates on every change, or a Redux-connected component that updates on every subscribed state change. Doesn't make a difference either way.
If you want React/Redux to be 'aware' of your leaflet widget, the only way to do that is to have it re-render on change. Bear in mind that a 'render' function doesn't just throw away and rebuild that part of the DOM, so re-rendering on every change won't cause your leaflet component to be destroyed and rebuilt.
You could connect the Redux dispatcher but not the state, so that you can publish changes to your server through redux, but not have the state connected. This doesn't seem like the ideal approach to use though.
Another approach is to have a 'persistedMapCoordinates' property that is only set when the user confirms their selection, but not on every change. That way the re-render only happens when they lock in their change, not on every small adjustment.
For doing the API calls, you'll want to use redux thunk and middleware. There is tons of info about this available online :)

If your component doesn't re-render, then I'd suggest not complicating it with Redux. It sounds like you just need a component that manages its own rendering.
var MyMapComponent = React.createClass({
componentWillMount: function() {
fetch('/some/data')
.then(this.update);
},
update: function(data) {
// calling setState will trigger shouldComponentUpdate
this.setState({ data: data });
},
loadMap: function(container) {
// calling setState will trigger shouldComponentUpdate
this.setState({
map: L.map(container)
});
},
shouldComponentUpdate: function(nextProps, nextState) {
var map = this.state.map;
var data = this.state.data;
// make updates to map here
// prevent react from re-rendering this component
return false;
},
render: function() {
// pass a reference to the dom node out to loadMap
return (
<div ref={this.loadMap}></div>
);
}
});

Related

Where to put socket.io code in a component?

I want to connect to the coincap.io public socket.io API. I have everything set up but don't know where in my component to put the socket.io code. Does it go in the constructor or componentWillMount or where? It's socket.io so it obviously always needs to be open so where in a component would that go? Here is the code I need to inject somewhere into my component:
this.socket = io.connect('http://socket.coincap.io');
this.socket.on('connect', function(tradeMsg) {
console.log("It worked");
});
Does it go in the constructor or componentWillMount?
Check these answers for details about this:
Can I call APIs in componentWillMount in React?
Why do the React docs recommend doing AJAX in componentDidMount, not componentWillMount?
Where in my component to put the socket.io code?
Use componentDidMount lifecycle method for, it will triggered only once after the component has been mounted successfully, we should write all kind of network calls inside this.
As per DOC:
componentDidMount() is invoked immediately after a component is
mounted. Initialization that requires DOM nodes should go here. If you
need to load data from a remote endpoint, this is a good place to
instantiate the network request. Setting state in this method will
trigger a re-rendering.
Write it like this:
componentDidMount(){
this.socket = io.connect('http://socket.coincap.io');
this.socket.on('connect', function(tradeMsg) {
console.log("It worked");
});
}
You can add socket code into 'componentDidMount`. refer link
componentDidMount(){
this.socket = io.connect('http://socket.coincap.io');
this.socket.on('connect', function(tradeMsg) {
console.log("It worked");
});
}

Defining attributes in React.js

I was wondering is there any difference between these two ways of defining React component attributes:
var something = React.createClass({
SSEStream: new EventSource("/stream/"),
componentDidMount: function() {
this.SSEStream.addEventListener("message", function(msg) {
// do something
}.bind(this));
});
var something = React.createClass({
componentDidMount: function() {
this.SSEStream = new EventSource("/stream/");
this.SSEStream.addEventListener("message", function(msg) {
// do something
}.bind(this));
}
});
Note the difference of how the React component attribute SSEStream was defined. My guess is that in the second example attribute is being recreated every time component is re-rendered whereas in the first it is created only once and therefore the first way should be preferred.
So the question is, will there be even the slightest difference between the two?
The difference between the two is as follows:
The first instantiates and sets a single EventSource at the time the component is declared, which is shared between each instance of the component.
On the other hand, the second creates a separate EventSource for each instance of the component, when the callback is fired.
Assuming that you want multiple instances of the component to be independent of one another, then I guess that the second option is what you want.
By the way, the componentDidMount callback is typically only run once in the life-cycle of the component, when the component is first mounted, so this has nothing to do with re-renders.

reactJs : Communication between two different components

I am new to reactjs. I want communication to happen between two independent components.
These components are not having any parent child relationship.
I found this piece of code.
I dont know how to use it
https://medium.com/react-zine/how-to-communicate-between-components-in-react-cc1ee986523a
From the docs:
For communication between two components that don't have a
parent-child relationship, you can set up your own global event
system. Subscribe to events in componentDidMount(), unsubscribe in
componentWillUnmount(), and call setState() when you receive an event.
Flux pattern is one of the possible ways to arrange this.
We use the PubSub pattern to attach global events, but as the docs say you can use many different arrangements.
Example using PubSub
Receiver component:
componentDidMount: function() {
this.token = PubSub.subscribe('MY TOPIC', this.subscriber)
},
componentWillUnmount: function() {
PubSub.unsubscribe(this.token)
},
subscriber: function(msg, data) {
console.log(msg, data)
// set state etc...
})
Emitter:
PubSub.publish('MY TOPIC', 'hello world!')

Flux pattern to initialize Store

Good Morning All!
I've a react Component (a View) that's dependent on a Store which is in turn dependent on having some state pulled from a round-trip to the server.
What I'm looking to understand is if there's a common pattern to solve for initializing the Store's state.
Right now I'm thinking I'd do something like:
var SomeView = React.createClass({
componentWillMount: function() {
SomeStore.addChangeListener(this._onChange);
// Go and tell this thing we want to initiliaze our
// state ahead of time. My worry here is obviously
// that when state is updated this fires again so I'd
// need to have some knowledge that the store has been
// initialized which seems very (very) kludgey
SomeActions.init();
},
render: function() {
// Here i'd want to see if I had items available for
// rendering. If I didn't I'd drop on a loading dialog
// or if I did I could render the detail.
},
_onChange: function() {
// this.setState...
}
});
var SomeActions = {
init: function() {
AppDispatcher.dispatch({
actionType: SomeConstants.INIT
});
}
};
var SomeStore = assign({}, EventEmitter.prototype, {
init: function() {
$.get('/round/trip', function(data) {
this.emitChange();
}).bind(this);
}
emitChange: function() {
this.emit(CHANGE_EVENT);
},
addChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback);
}
});
AppDispatcher.register(function(action) {
switch(action.actionType) {
case SomeConstants.INIT:
SomeStore.init()
break;
default:
}
});
I am absolutely positive there must be a better way.
My worry here is obviously that when state is updated this fires again
componentWillMount fires once component injected to DOM, state updates will not fire this method. However, if you remove component from DOM (for example: not rendering it in parent component based on some condition) and render it later, the method will be fired again. So init will be called multiple times on the store.
I believe you should move http request code to Web API module and fire an action to the API from componentWillMount method, the API will then trigger the store and fire change event on the component, which will update the state and re-render. This is how Flux works.
If you need to get data only once and you know your component is going to be removed from/added to DOM multiple times, you should put a call to the api into upper component in the tree (component that represents an entry point to the widget or something).
I recommend to check Component Container or Higher-order Components pattern, which basically defines a thin wrapper component as a data layer over the view component. Thus you can completely separate your views from data layer and it works good.
You may also want to check another approach, coming from ClojureScript's Om, with a single immutable state. This simplifies everything even more and actually the best way I've found for my self to build apps with React. I've create a starter kit for it, there's a good explanation of main concepts in the readme.

Login ajax request Flux React?

How can I do
after login form submit (React Component)
using flux structure
ajax request that provides response ?
Can you provide some example ?
Basically you need to make an Ajax request, and then create success/error handlers. Inside those handlers, you will create actions to inform your stores of the result. It's probably a good idea to have an AppStore or SessionStore or something that will hold the data related to the current user and the auth token. Your controller-views can listen to that store and render their children when the current user becomes authenticated.
Here's how i made:
When my component bootstraps, I fire an INIT action to the Store which initially gets the datas i need. Here's the simplified data flow
After login my Library component is rendered so i need to initialize the data (books, users etc..)
Library:
componentDidMount: function() {
Store.addChangeListener(this._onChange);
Actions.initialize();
},
As you can see, when my component did mount, i fired a new action, and my store will handle this action.
Store:
switch(action.actionType) {
case Constants.INIT:
_init().done(function() {
Store.emitChange();
});
break;
I'm calling the private function _init() which will return a promise object. When the promise is Fulfilled the Store is ready to emit it's change event.
In _init I'm simulating some async data loads, thats why i made the promise, here it is:
function _init() {
var loadBooksDeferred = new jQuery.Deferred(),
loadUsersDeferred = new jQuery.Deferred(),
loadCategoriesDeferred = new jQuery.Deferred(),
stateReadyDfd = new jQuery.Deferred();
_loadBooks(loadBooksDeferred);
_loadUsers(loadUsersDeferred);
_loadCategories(loadCategoriesDeferred);
jQuery
.when(loadBooksDeferred, loadUsersDeferred, loadCategoriesDeferred)
.then(stateReadyDfd.resolve, stateReadyDfd.reject);
return stateReadyDfd;
}

Resources