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.
Related
I'm working with a react app and currently working with a feature. The main task is showing some charts by getting data from API. And these charts will show the last 30 minutes' data.
I have questions,
In this situation, is it necessary to store these data in the state by Redux, though it can be handled at components very easily? And every time I refresh or request, I get new data (log base data).
When do we make the mind to store data in state and when not?
A redux store is a singleton, thus a single source of truth that can be made available to all components in the whole react application. If your state is intended only for one react component then you don't need a redux store. A useReducer react hook allows to well reproduce the redux pattern in a single component. Stick with a useReducer hook for a single component and use redux library for a store available to an app composed of several components.
Redux is not designed for the specif role of a special type of data.
You can use still store your temporary (30 min) data into redux, and use it to cross your feeling the same as the rest of your data.
But in this case, you might need to reset data after 30 minutes or invalidate your cache, keep your eye in react-query and RTK-query handling these types of actions more easily for you.
If data is being used for many states or those data are being used by many components then you should use redux. You can still go without redux, it is up to you after all.
If you have various components and routes then redux will help you to reduce the codes and also make the codes simpler.
Redux will give the one store for all the components in the project to store and access the data which is better then context or props tricks.
Also if you want to achive something like if user opened two different tabs. Let it be same page or two different pages of your website and if user done an action on page A and you want that page A or page B opened in another tab should get that update then redux can let you achieve that. Context and props passing are not useful in this case.
https://redux.js.org/faq/general#when-should-i-use-redux
Redux is most useful when in cases when:
You have large amounts of application state that are needed in many places in the app
The app state is updated frequently
The logic to update that state may be complex
The app has a medium or large-sized codebase, and might be worked on by many people
You need to see how that state is being updated over time
I currently have a React app that I'd like to use SSR with. All but one component is pretty much static content, making SSR super easy. Everything but the component is rendered just fine and well right now.
My question is how do I go about rendering this component that needs to first get data? Because it's a complex SVG that gets rendered my line of thinking is that having it "update" once data comes in is a bad move, and it would be better for it to just not exist in the absence of data (with an error message).
So here's my plan: I can add a prop to the component to pass in data from a parent rather than keep it as internal state only. So if data is passed, no fetch request in the component is necessary. From there what I can do is take the static bundle output of the app and, when the page is requested, the server will request the proper data just as the component would. Once the data is received, the server can grab the component from the bundle with regex, add the data as a prop, render the component, and stick it back in with the rest of the already rendered static content.
Is this the correct way to do this? It feels a bit complicated, but that might just be how it's done. I'm not sure.
Your intuitions are correct. In current React (17.0), it's quite cumbersome to do SSR with data-fetching inside components.
What needs to be achieved on a conceptual level is that all data dependencies need to be known upfront, ie. before calling ReactDOM's render. This way, one can access the data in a synchronous manner which allows to do one-pass render on a server.
I don't quite follow your idea to "grap the component from the bundle with regex". One way of solving the data dependency problem is to inject the data into React tree from the root component (ie. ReactDOM.renderToString(<App componentStaticData={data} />)) and make the data-dependent component aware of the fact that it can just grab the data from there instead of doing (asynchronous) call. It's important to note that useEffects are not executed on the server.
Another idea to grab all the data dependencies is to do two-pass render. First one is used as a way to collect all resources used, then we await their completion and inject them as static data into send pass.
Third way is to use one of the React frameworks that provide SSR out of the box. You can have a look at (among many others) Next.js or Gatsby. Depending on your setup, this might be easiest or the hardest way to achieve SSR.
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 Have react app which contains many pages. For each page i added store. I using params from url for example photoId then passing to actioncreator which call service and then dispatching data to store. In page component i have store listener. Store imiting change and listener calling render for new state.
Store and action creator relates to this page only. How to create pages more simple?
Thank you!
The Flux model (using actions, dispatcher, and stores) works well for larger apps where a data fetch may affect many components and pages. If you think your app will grow then it may be worth the extra verbosity. If you're keeping your app small then composing plain React components is a great way to keep things simple and there is nothing wrong with doing it as long as you separate the data operations from the display, the way your linked example showed. Have fun!