react redux change query params with components - javascript

I have an isomorphic react application using redux,react-router, react-router-redux, I want to bind my components with url query params and when the query params changed, send request to an API and update my state and finally fetch data.
I know with react-router-redux it automatically update my state.
Also I want to show a pre-loader (spinner) to user when data is fetching.
what is the best way to write an action creator for this issue ? thanks

I want to show a pre-loader (spinner) to user when data is fetching
Pass a data prop to your component. When it's undefined, show a spinner.
const MyComponent = (props) => {
if (!props.data) return <Spinner />
...
}
When the query params changed, send request to an API and update my state and finally fetch data
The most simple solution (this can get quite complex depending on your needs) is to fire this logic on the Component's lifecycle hooks.
When the route changes react-router, with a typical configuration, will cause the component to render if you were previously on a different route, and update if you were previously on the same route (i.e. the same path, but with different query params).
So for the first case, use componentDidMount, for the second case, use comonentDidUpdate(prevProps, prevState) lifecycle hook.
To map the asynchronous API call to redux action(s), use a library like redux-thunk or probably more tailored to this use case, redux-promise-middleware. How to use those is a bit deep in scope for me to go into here, but they both have excellent documentation.
In the end, you'll want to map those actions in a reducer put the response data somewhere in your state tree, then using react-redux bind that location in the state tree to the data prop on your Component, as I mentioned before.

Related

How to make multiple api end point calls in sequential order with react redux javascript?

I have a redux store containing multiple states which is populated by same api but multiple end-points.
I have a react app with multiple components, which access to one of these states, and they all call to the correspondent api no mount by dispatching a async function (redux-thunk) to the store.
In the App.js multiple components are used.
Problem:
When all the components mount they call to the api concurrently and exceeds the maximum number of call allowed for the short time frame. Thus all calls reply with status code 429: Too many request.
*Extra notes: I'm buliding a news web-app, and using gnews.io api with multiple search queries and end-points to get data.
In your case i believe one approach would be to create a request type and use it in your state instead of the raw value returned from the endpoint, something like:
type TApiRequestState<T> = {pending: boolean, response: T}
When you dispatch an action that will trigger the endpoint in thunks you would set the api state to loading.
After that all you need to do is check if the request is not already running on the other components.
if (!value.pending && !value.response) {
dispatch(thunksFn)
}
In theory you could dispatch all of the initial requests on a parent component and only render these child components when the initial requests are done. But this depends on a project to project basis IMO.

storing data in state when data is fetched using graphql and apollo client

I have been using react and redux and everytime ,I make a call to some rest api in ComponentDidMount ,I can set a state with it and pass that state onto my child or change that state and play with it .
I can keep that data in my redux too and do all what i want .
I recently started using graphql and I see that as one fetches data inside render using a query , we render the data that we want to and so on .
But I am concerned as how instead of rendering it ,I can store it in some state ,play with it and then pass it down to the child .
I came acroos this link state in apollo but couldn't have a clear understanding of it as what it basically does ?
How to solve this issue of state management and playing with that state which is set by the data coming from the apollo .
I am really missing out this feature of
this.setState({
data:(some api data )
)}
Suppose I made a query and I want three of my Child Components to share the same data .How will you achieve this with graphql ?
1st method
Data read from api is accessible via the cache - default policy is cache first. Each of children can access data from cache using graphql (HOCs or components). Each of them can use a different query to get data the component really needs. If all of queries fields are subset of parent query - you can use cache-only policy.
2nd method
You can manipulate api data using getDerivedStateFromProps(). You can pass these values directly as props to the childs (w/o using graphql cache access).
3rd method
React classic (pass props down the tree): simply pass data prop (unmodified) to child rendering <Child data={this.props.data} /> (parent inside HOC) or <Child data={data} /> (render prop within <Query/> component)

Component makes a GET request on mounted() and props response to child component. What happens if I type URL that goes straight to child component?

So imagine I have these 2 URLs:
example.com/Profile
example.com/Profile/City
When example.com/Profile is visited, I present component Profile and when example.com/Profile/City is visited, I present component City.
I need to make a GET request that returns information used in both components. Currently, I make that GET request in the mounted() lifecycle hook of both components but I have been wondering if I can do it once only in the parent Profile component and then just props it down to City so that I could get rid of 1 GET request.
However, I am not sure what would happen if a user straight up types example.com/Profile/City? Considering the GET request is executed on mounted() of the Profile component and we haven't mounted Profile since the user straight up typed the URL that leads to City component , will I have the response in the child component?
Considering the GET request is executed on mounted() of the Profile component and we haven't mounted Profile since the user straight up typed the URL that leads to City component , will I have the response in the child component?
No, you won't. You will end up with no data.
I have been wondering if I can do it once only in the parent Profile component and then just props it down to City so that I could get rid of 1 GET request.
Not really. However if you used a global state management solution like vuex, you could move the request and the data into this global state and trigger the vuex action for the request from both component's mounted.
Then you could implement logic in your vuex action that would skip the request if the data is already present (i.e. from having previously visited /profile). But in that case you should make sure to save some timestamp so you don't cache the data indefinitely.
If you expect the data to change frequently, I wouldn't cache it like that at all and rather do a duplicate request everytime to ensure the data is a fresh as possible.

How to 'freeze' redux state during a route change?

My app uses react-router, redux, react-redux. Lets say I'm currently looking at /about route which renders the AboutPage component. Now I want to navigate to /news. Right now, when the route change happens the new component mounts, which fires off async actions to fetch the data. While that data is being fetched I am looking at the NewsPage component but with loading spinners.
What I'm trying to do is stay on the AboutPage component while all that data fetching is happening. I have successfully implemented the data fetching during react-router's onEnter hook. The problem is that, if AboutPage happens to use any of the same redux state as NewsPage, you'll see rendering changes while the data is being fetched and updated.
What I'd like is to somehow 'freeze' the current route while actions/state-changes are happening behind the scenes, and then render the new route component when thats ready (in the meantime users will see loading feedback via https://github.com/rstacruz/nprogress).
So either I need to completely unsubscribe the current route component from state changes or otherwise lock stuff in. Not sure if redux even exposes what I need but curious if others have solved this.

Pass Props Between Routes Using React-Router

Is the only way to pass data between routes in React-Router (1.0.0-rc) url params? I have a component, A, which uses the History mixin, and has an event handler that makes a server request and then calls that.history.pushState(null, '/B'); to transition to route B handled by component B.
Now, I would like to pass some of the data I am returned by the server to component B as a prop (e.g. "login successful"), or somehow affect the state of B, but I can't find any documentation stating this is possible. Is there any way to do this, or do I need to pass it as a url parameter?
You have two options:
pass the data as a query params
keep the state of the application somewhere else, outside of the routes
For #2 you could use something like redux which will keep a 'global' store of the application state. You can then access this state from both component A and B.
Use localstorage or sessionsessionstorage. Set data in first router, get it on second router using set and get item of localstorage
https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

Categories