I have a component as 'middleware' where it check for condition and trigger some function, it work when user enter into the page (I mean initial load) or user refreshed the page. But componentWillMount or componentDidMount won't trigger if user enter the path via <Link>?
https://codesandbox.io/s/r433m6kvvp
Because componentWillMount and componentDidMount are the mounting methods, not updating methods, they will not get called on component re-rendering.
Solution:
You need to do one change, put the BrowserRouter here:
render(<BrowserRouter><App /></BrowserRouter>, document.getElementById('root'));
And use componentWillReceiveProps inside Auth component, for initial rendering componentDidMount will get called and for each route change componentWillReceiveProps will get called, you can execute the function at both the places.
Working Code.
Related
Given following middleware, whats the best way to rerun the logic when ever store.getters.authenticated changes, and not only on the initial load.
middleware/auth.js
export default function ({ store, redirect }) {
if (!store.getters.authenticated) {
return redirect({ name: "login" })
}
}
You asked how to rerun it inside of the middleware itself, which is the 2nd part of a possible middleware trigger (like if the user is not authenticated anymore while staying on the same page) and without any specific action, like when using polling or websockets I thought.
Meanwhile, the 1st part is the easiest: call the middleware globally (in nuxt.config.js) to trigger it on each page navigation.
If he stays on the same page, you can also move with the router as you did but at this point, checking if there is an error in your axios is maybe more appropriate since it's the initiator.
I also do like to use this.$nuxt.refresh() to trigger all the checks when switching accounts globally, helps re-running all those tasty fetch() hooks.
So my query is that is there a way to get Vue-Router to execute a function/method after route changes? More specifically, after the route has been mounted successfully.
Currently, I do loading function that evaluated to true once the user clicks away from the initial screen. And each page has a mounted function (repeated across all my vue pages) that sets the loading to false.
I want to have it such that the router detects this change, sees if the new routed component has been mounted and then executes a function to set the loading to false.
I use a dedicated router.js file to contain all my routes and params for it and then call that file in the main app.js file that mounts the view for the user.
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.
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.
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.