Setting defaul state in a reactivejs/redux app - reactjs

In my current ReactJS component, I have to call a REST API and get the JSON. It is done in componentWillMount.
I have introduced Redux in my app. Where should I make the call now to get the JSON and set as the default state? Is it in Redux or my React app?
Any example appreciated.

You'll usually want to dispatch an action from componentDidMount (or Will depending on your lifecycle constraints). That action will kick off the XHR and usually return either a thunk (redux-thunk) or a promise (redux-promise-middleware). If a thunk, it will be set up to dispatch another action with the results, or with a promise it does that for you, then reduce that state in as per normal and bind it to the component.

A common practice is to have a configureStore.js file that exports a configureStore() function that handles the store setup (initial state, middleware, and enhancers) and returns your store. See the "real-world" example in the redux repo for an example of this.
In your case, a simple approach would be to request the data from your REST API when your app starts up, and then when you receive the response, call configureStore(initialState) (where initialState is the data you fetched) and then proceed with the rest of the app setup and initial rendering. This approach will add a little time to your app startup though, because its initialization will be paused while it's waiting for that API response.
Another option would be to just create your store normally (without the prerequisite API fetch), and then make the actual initial state request from your API after your store has been created. When that API response is received, you could dispatch an INITIAL_STATE action, and have reducers ready to handle that. In this approach, you'd probably want some sort of loading indicator in place during this initial fetch, since your app will have rendered or at least started to render during the API request.
If you're doing server rendering, you can just fetch the initial state data from the server side, and attach it to the window object of the index.html that you're rendering. See the "universal" example in the redux repo for an example of this. That'll allow you to simply grab your initial state from the window object when you create your store.

Related

When should application state update the database?

Im currently working on an application which uses react, redux, graphql, apollo and MongoDB.
When the application first loads, im looking to populate the application local data using the database, from there use the application state for any further display to the view. My problem is, im not sure when to make a call to the database given this particular stack
All service call should be done in componentDidMount() life cycle method or you can Use middleware like thunk to call sync service call or db call.
componentDidMount(): After mounting component call service and set state, this state will be used on UI to render any data.
Middleware: You dispatch an action like load products. This will call middle ware to call service and store details in redux store. This can render data on UI.
Let me know if you need more explanation. This is most common architecture which people use for react apps.

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.

Redux equivalent for Angular2 services

I come from an Angular2 world where there are services that do the normal data loading and so on, now I am on a React, Redux application and am trying to figure out what is the equivalent to Angular2 services in Redux (React). Is it Redux-thunk?
The answer is yes and no.
Yes
Angular services have the logic to load data and normally return a Promise object that gets resolved with data loaded.
With Redux Thunk middleware, you create asynchronous action creators where you put the logic for data loading. But instead of returning a Promise object directly, it waits until the data gets resolved and dispatches an action to update the state with data loaded. React components receive data from Redux store via props. (See connect() method from react-redux.)
No
Angular services are singletons that provides a specific functionality, like $http for facilitating communication with the remote HTTP servers.
Redux Thunk is a middleware and does not do anything but to allow you to write asynchronous action creators that can delay the dispatch of an action, or to dispatch only if a certain condition is met. The action creators are functions that create actions - they are not intended to provide other functionality, like communication with backend servers.
With that said, it is often a matter of coding style where and how you write the logic to load data.
You can use the Fetch API or its polyfill function, or axios library, both are Promise based. You can also consider using Observables, but it is beyond the topic, I think.
As you do with Angular services, you can put all the related logic in a single location and export them. In your action creators, you call these wrapper/helpers, listen for resolution/rejection and dispatch an appropriate action with data resolved as a payload.
Your reducers update the Redux store upon receiving an action dispatched and these state changes are propagated to React components. And this is how the Flux architecture works and how the data flows from Redux Store to React components, AFAIK.
(I might be wrong, please correct me if anything is incorrect and I am open to your opinions. I am still on the way to figure out the best practice to implement services in React applications.)

react redux synchronous call

Building a React application with redux as the flux pattern.
To use an api a token exchange request needs to happen. This has to occur only once when the React application starts. The access_token returned from the token exchange needs to be stored in the redux state and accessible by other api calls.
One approach i tried is by calling a redux action in the App(parent) component, and then all other calls are within children components. New to React i now understand that this is not the right approach as the React components lifecycle events and the actions and reducers called do not follow a synchronous flow, so the redux actions are called asynchronously.
How do i ensure a redux action is called prior to any other redux action that depends on the results of the first redux action? Which middleware would be best suited for ensuring a synchronous approach redux-thunk, redux-look and redux-saga.
If you need a process to run before any other action, you could do it before creating the store, and passing the result in your main reducer function at store creation.
Then, just render the app after the promise or callback of this process is done.
Otherwise, just dispatch this initial action after the store creation, and before app render (with redux-thunk if it is async).
You can use redux-thunk to have a "promise like" behavior when displatching actions. This way you can ensure an action was done before dispatching another one.

Flux: How to make an action wait for a store?

I'm tying myself in knots with a React problem which I'm sure can't be as difficult as it seems to me right now.
I'm building a single page app against a RESTful server API that returns resources, together with links that describe what can be done with that resource. And I'm trying to ensure that my client's ajax calls only use URLs retrieved from the server in this way. So, for example, my LoggedInSessionStore contains the URL that allows me to fetch the list of all public documents, say.
The problem I have is how to manage the dependencies between actions and stores. For example, when the action to fetch all public documents fires, it needs to get its URL from the LoggedInSessionStore. But that store may not yet have been populated yet; so the action must not fire until a previous action (fetch the login session) has completed.
So, I want an action that can fetch server data using a URL that is stored in a store. What is the accepted way to ensure that the action cannot fire until that store has been populated?
TL;DR Don't store your URLs in your Stores. Let your actions handle API calls.
In general when using Flux your actions should not know about your stores. Data in a Flux application is meant to flow in one direction:
Components --> Actions --> Dispatcher --> Stores --> Components
Your React components create actions, which are then dispatched by the Dispatcher to your stores. Stores will be notified of the actions via their registered callback and will update themselves accordingly. Components will listen for stores to update themselves and they will update their own state accordingly. Thus the circle is completed.
The point being: Actions should not depend on stores
What I would suggest is that you move all your API logic into actions. This includes the URLs for your API. This is a fairly common pattern in Flux applications:
A component triggers a fetch action on componentDidMount. Displays loading spinner since it does not yet have the data it needs to render.
The fetch action makes an AJAX call to fetch data from the server.
When the data comes back from the server, the action dispatches it as a payload
A store sees the payload and sets its internal state based on the fetched data
The component sees that the store has been updated, and updates its own state accordingly. This causes it to render the app instead of just a loading spinner.
An alternative option is have your fetch logic inside your stores, including the AJAX request code. I find the former easier to reason about (stores know nothing, they just react to data when its available) but it's up to you how you want to implement it. Just make sure that the API fetching logic is in one place only, not split between Actions and Stores.
This thread may also be helpful: Should flux stores, or actions (or both) touch external services?

Resources