react-router and flux - clearing state while transition - reactjs

I am using react-router with the flux architecture (facebook's flux implementation).
Currently in my system I have route that says "chat/:topic".
When the user is entering this component, I am creating a subscription (using action creation, on componentWillMount) to a websocket server, and I am removing the subscription on componentWillUnmount.
When the user is moving to another route the whole workflow works alright - because react-router is unmounting my component.
When I transition inside my route (from "chat/games" to "chat/tv"), the component isn't mounted and I need to clear my state of the components.
I read about different actions that I can take and this on transition to dispatch an action "TRANSITION" and every relevant store will clear it's store.
In my opinion, this kind of action - is wrong, it couples my stores and my router.
How would you solve this problem? Is this an issue that I should raise to react-router and ask them to unmount inside my route?

I found the answer thanks to gaearon (https://github.com/gaearon/),
Use a store to keep the selected topic and ask the messages store for messages, in flux you shouldn't remove anything from your store, unless you need it for a performance reasons.
In my application, I must remove the messages (since they are large objects) and clear my subscriptions (to reduce the load on the server).
In order to achieve this there were three solutions that I found:
Use componentWillReceiveProps and check if the params are changed, if the params are changed - do whatever you need in order to clear the store - for example call ActionCreator and reset the state.
Send a dispose payload in transition (inside Router.run) which will tell all the stores to clear themselves.
last solution (which I used) making sure that my components are unmounted - Why? It is too error prone to clear the state on componentWillReceiveProps/dispose and it is clearer to just ensure the components are unmounted.
Details on how to achieve this:
https://github.com/rackt/react-router/issues/292
https://github.com/rackt/react-router/issues/496#issuecomment-64152941

I believe that compomentWillReceiveProps might solve your issue. This is what react router uses to pass stuff to you.

As far as I know, you need to use both componentWillReceiveProps AND componentDid/WillMount to catch the initial render also.
I'm anxiously awaiting the react-router 1.0 release (this weekend?) in hopes that there is a more elegant way to do this.

Related

Add the auth state listener to every component that needs it or can I add it only to the main App component and provide it furtther as a context

I was wondering which one is a better practice for a React app with firebase, I understand from the firebase docs that I should add it on every page that needs it, bu I was thinking that it would be easier to provide it as a context to all my components since pretty much all of them are relying on the user state to display the right information. So which one is better ?
I have tried both but I do not know which one is better in terms of best practices or when to use each approach .
Neither of these is pertinently better than the other.
The Firebase SDKs cache the auth information already, so adding an auth state listener in each component does not require extra calls to the server.
But there's also nothing wrong in principle with getting the state once at a higher level component and pushing it down into child components that needs it. Just make sure to re-render those child components when the auth state changes.

About calling API in reactjs

I have a question about calling API in react.
Example in the website. We have a lot of page. Each page has a lot of components. And each component has its own data need to get in server.
I see we have two way to call API is:
First. We call all API of each page in a root of each page then set the data to state. After that, we pass data to children Component.
Second. In each component, we call its API to get its data then set the data to component 's state.
So which is better. I need an explain about that.
Thanks you,
There are many ways to pass Data through out the components.
If the application is small and there are small number of child components you can go by making calls in Root folder.
There would be some components that always doesn't render and only rendered based on specific conditions at this point you can go by making calls from that component.
Using redux and redux thunk is always an option if the data is needed in many components and data can be accessed at any point of time.
As noted in the previous answers/comments you could do either one of these. If you plan to use redux it might be easier to chain the api calls in a single action w/ thunk that gets ran on main component load.
Context or Redux would do you well so you don't have to pass tons of data through prop levels.(prop drilling)
I would suggest Redux, IMO context gets too cluttered and by the time you've properly atomized your code to clean up everything you may as well have just went through the overhead of adding redux.
What you should ask yourself is-
Does it make sense to have all this data load at the same time?
Is it appropriate for some api calls to be made from the components that will use them?
You have creative license to do what works best for you.

use state if i'm using redux

if I'm using redux and redux saga to manage state but a lot of times I wanna do API request for something and I need the result only at this component is it ok to just use state?
or this considered a bad practice because the idea behind redux is that all the states should be in one place
In my opinion, it is fine to do it in certain situations. However, you need to be aware of a situation when the request is pending and the user already navigated to a different page of your app. When a request comes back it will try to do this.setState on unmounted component!
So I think is that you should trust your instincts on this one :)
You probably have already seen it, but I will share it anyway. You might not need redux.

Appropriate place to dispatch action for fetching server data

I'm new to React and I'm trying to figure out the best way to request information from the server based on the URL. I'm using Redux and React Router v4.
Let's say I have a route /foo/:id, and a component Foo that will render something based on id. However Foo needs some server data related to id to do so. I believe the way to accomplish this would be to use mapDispatchToProps to create a function that takes id as input, does some async work, dispatches an action, and ultimately updates the redux state.
My question is: where is the most appropriate place to invoke the dispatch? In this scenario, there's no form submission or button click to kick things off. Originally I was thinking of including a check for the id data in render() and fetching if it was not populated, but this felt wrong due to the side effects.
You can do it in componentDidMount of the Foo component, similar to this example from the Redux GitHub project.
Your intuition is right that render is not a good place to do so. Most people do it in the componentDidMount lifecycle method of the component.
On a relevant note, you will also want to do fetching also in the componentWillReceiveProps method like what they did here. Reason being if your user navigated from foo/1/ to foo/2/, the component is already on the screen and will not be mounted again, hence componentDidMount will not be called again. The fetching for the second user will be done in the componentWillReceiveProps method.
i think the best way to do the dispatch inside the componentWillReceiveProps() which would help you fetch some data before the component renders
It seems your use case is well-captured by the react-refetch package which you can find here. It provides a higher-order component that allows you to specify dependencies at specific API endpoints and then resolves them when a new instance of your component is created.
Importantly it injects the data into your components props using a synchronous abstraction of a promise called a PromiseState. This will allow you to conditionally render your component depending on whether the data is say pending, fulfilled, rejected, etc.
This is not attached in any way to Redux, it skips that layer entirely, so do keep it in mind that the response is directly injected into the component and does not go through your redux store's state.

What is the use of Redux-Router in addition to reac-router?

guys. When I go through the documentation of redux-router, I just cannot understand why do we need it?
Here is what the documentation is trying to explain:
React Router is a fantastic routing library, but one downside is that
it abstracts away a very crucial piece of application state — the
current route! This abstraction is super useful for route matching and
rendering, but the API for interacting with the router to 1) trigger
transitions and 2) react to state changes within the component
lifecycle leaves something to be desired.
It turns out we already solved these problems with Flux (and Redux):
We use action creators to trigger state changes, and we use
higher-order components to subscribe to state changes.
This library allows you to keep your router state inside your Redux
store. So getting the current pathname, query, and params is as easy
as selecting any other part of your application state.
As far as I can understand, it is trying to say redux router can keep router state inside redux store so that we can get route info more conveniently.
But within react-router, I can also easily do it.
Like path="messages/:id", I can use this.props.params.id to get the params.
Can someone explain in what scenario redux-router bring its benefit?
Redux (and in general, the flux pattern) is all about having the entire application state stored in one central place. This has the benefit of easier debugging and makes it easier to implement certain features.
If you've ever used the redux-devtools in a react app with react-router, you'll notice that its only of limited use, because you can't replay the entire lifecycle of the application. When the user changes routes, that's not recorded in the redux store. Redux Router keeps the route state in the store.
You could use this for debugging, you could serialise the entire store history and log it elsewhere to replay user sessions. You could hook into it to implement full undo, or log analytics events.
redux-simple-router is a library which could help you understand how to use react router in a redux application.
It is a very simple library stores the URL in redux state and keeps it in sync with any react-router changes.
redux-simple-router compared to redux-router is:
Much smaller and simpler. You don't need to learn another library on top of everything else.
Encourages direct access of react-router APIs. Need server-side rendering, or something else advanced? Just read react-router's docs.
Only stores the current URL and state, whereas redux-router stores the entire location object from react-router.
Follow one of the these 2 examples to get up and running:
redux-simple-router-example
redux-frontend-boilerplate

Resources