Pass Props Between Routes Using React-Router - javascript

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

Related

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.

On Multiple Components the same Model/Data

i am trying to code a simple dashboard with React, node and mongo.
Register and Login works well:)
So now i want to display the User Name on the Topbar with his Picture. I load the data (name and picture url) in the Topbar component via Ajax from the Server. So right, soo good.
Soo, but i need User Data for a lot of other components. (Friends, Notifications and soo soon) i can't in every componente an ajax call to my server make or? But i don't understand how to do this.
I need Data from the same Model in many different components.
You can use the context api or redux to create a 'global' store and access any data in it from anywhere down or up the component hierarchy without having to pass props down each level. In redux you can access any piece of this global state with the connect hoc.
More on redux
More on context api
Comparison of the two

react redux change query params with components

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.

LocalStorage with react-redux

I'm using React and Redux for my SPA and I want to store some data locally. And I need to synchronize appState with localstorage, so my data won't be lost after refreshing the page.
I'm completely new for React and Redux and have not much of understanding what's going on, but as I think Redux creates for me that state of entire app, so I can't just bind my state with localstorage in app component because it'll be just state of component and not of my app.
I would suggest storing the data in local storage with the following commands.
Set the data in localStorage can be done with the command:
localStorage.setItem('nameForData', variableNameForData);
To retrieve the data when required.
var variableNameForData = localStorage.getItem('nameForData')
To remove the data from localStorage:
localStorage.removeItem('nameForData')
These would typically be put inside action creators with a dispatch to change the state of some Boolean that tracks the applications interaction with localStorage.
For example you might have a state that is set to true when the local storage is created.
On refresh you might call an action creator that checks the local storage exists, and if it does set that boolean back to true or if it does not exist you are back to creating local storage and then set it to true.
You could put this function in componentWillMount(){} and it will be called when the component is first rendered, and thus in the case of a refresh.
Docs for component life cycle and specifically componentWillMount here
Docs for local storage here
I can suggest you to store the state after each action. For that you can use a localStorage middleware that only store the whole state object.
Then in your createStore part you will retrieve the initialState from the localStorage API.
In that case you don't need to modify any component, juste the initialState from localStorage and the middleware that save the state

Categories