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.
Related
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.
I'm working on a React+Redux application. I'm calling APIs through Redux actions and storing the response data in the Redux state. But there is a case, Where I don't have to store the API response data in the Redux store.
So the question is, Is there any valid reason to call the APIs through
Redux actions or Should I call the APIs directly since I'm not storing
the response data in Redux store?
It depends on what kind of call you're trying to make, and who's concern it is.
Here are a few cases:
Is this a one-way call to track something?. You can fire an action that gets picked up in a middleware. this is a good case for sending analytics.
This doesn't have to be stored in Redux's store.
Is this a call where some other part of your application will need this data?, then this is a good use case for making an update in the Redux Store so other components when read this and use props to decide what to render etc.
Is this a call where it only concerns one component or isolated part?. You can make this call inside the component in componentDidMount since this doesn't concern anyone else
Alternatively take a look at Sagas, they observe all actions that get dispatched and decide what to do with them in a clean way.
The accepted answer quite well explains the scenario where from API call can be initiated. For better user experience, we always show some spinner or busy sign to inform the user that a request is being made and it has not finished yet. It may happen that API response is not mutating the state, but to let the user know some task is going in the background, we usually update store (for global access) or state (for component level access) with value like isFetching or anything meaningful.
So, it depends on the developer, whether he/she want to show some busy sign or silently perform the API request. Moreover, if they want to show busy sign then, they should decide which part of the application should be aware of the API call. If it is restricted to the component level only, then no need to make the call in actions, otherwise, for global level, yes it should be inside action.
For the sake of uniformity, you should always follow the redux way, even though all the responses are not stored in Redux. It is also a question if you are not using the response from an API call why are you making the call. This argument is counter-intuitive. If you are using the response in some way better do it the Redux way. It is advised to always store the response to a call to Redux and use it, I am sure you are making API calls to do some action on UI.
So I may be asking the wrong question, so please leave comments and I'll adjust. I was told by another developer that when using redux, I should do ALL API calls within actions and create reducers for them. But I feel that sometimes making the call directly in the component will save me a TON of code. Are there best practices for this sort of thing?
If the data you are getting from the API is only going to be consumed by a single component then you are fine to write it as part of your component (or better still, a container component). I believe the rationale behind doing your API calls in actions is to ensure that the single source of truth is maintained (the main reason to use 'the react/redux way' for me personally). If you are bringing in data from your API that is to be consumed by multiple components then use redux to ensure the same state is maintained by redux and passed to all components that use it.
This was previously answered by Redux's creator, Dan Abramov, here: Why do we need middleware for async flow in Redux? .
The summary:
It’s just inconvenient in a large application because you’ll have different components performing the same actions, you might want to debounce some actions, or keep some local state like auto-incrementing IDs close to action creators, etc. So it is just easier from the maintenance point of view to extract action creators into separate functions.
I realize this question has been asked before and this topic has been widely discussed in the Redux community, but I have not seen it approached by this angle: Error messages.
In most examples using React + Redux + some middleware (redux-promise and redux-thunk), external api calls are done inside the action creator. The result of the API call then affects the application state with a success case or error case.
My counter-argument:
The main interested party in the results of an API call is a component, particularly because it's the one that has to often show an error message to the user. Error messages are best set as component state. It's easier to "clean up" on componentWillMount. No need to create an action just to clean up an application level error state.
All API call's should be made from a component and it should decide what action creator to call. Action creators then become JUST that, functions that return objects. No side-effects in them.
Again, I stress that this "take" is based on the fact that most of the time, a component will need to handle error messages anyways. So why not call the api and deal with the error right there? Things go ok, call an action creator. Things go bad, show an error. Also, I don't think there will be duplication of API calls across the application. After all, React tries to enforce modularization and top-down flow of data. Two different components really shouldn't be calling the same api. They could call the same action creator though and that's fine. Think sign up and sign in. Different api endpoints. Same final state (authenticated: true)
Anyway, this is my view on it. I'm hoping that someone with more experience will answer if API calls inside components are a good idea. Thank you.
EDIT: Just created this post on medium, which hopefully explains my argument better
Kind of too open ended to come up with a "solution" but here's a short answer.
First off, what do you mean it's easier to clean up on componentWillMount? Many times api calls are done on an already mounted component like a sign up or login component. The API call happens when the button is clicked, not when it's mounted.
Also, the main reason why API calls are done outside React components (assuming you have a data handling framework like redux) is that the library is used as a View layer. A component renders HTML that declaratively reflects the state of your application. When a login API call fails to authenticate, the application state is what changes, and as a result the View. If you start to handle API responses in your component, you may run into issues with out of sync state.
For example, the user logs in 10 times with the wrong credentials and gets "locked out". How do you handle that error? You'll likely add some logic to handle those errors. And what if other parts of the app need to react to this error? Now you start to fire actions based on those errors and essentially go back to making your API calls entirely from an action creator, which happens to live in your component.
Now, this mostly applies to large applications. It's perfectly reasonable to handle API calls in a component if the application is small enough and state management frameworks like redux just add bloat. If it's a large application, however, I still highly recommend keeping API logic in the action creators.
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.