First of all: I know that this question has already been asked here and that there is also already a solution. Please read the whole post before marking this as a duplicate
I am using the HashRouter from react-router-dom and I have this simple route:
<Route path='/folder/:folderId' component={FileArea} />
The routing works fine but unfortunately my componentDidMount function is not being called after a route change. This is crutial for my application to work as I have to make an API Call every time the route changes to retrieve the corresponding data (according to the folderId url parameter).
I found a solution in the internet using componentWillReceiveProps and this would work fine for me but apparently this function will no longer work in future react versions: React Documentation
I also know that I could theoretically use static getDerivedStateFromProps(nextProps, prevState) but this function is called way to often and it would be rediculous to make an api call each time.
Is there an alternative for componentWillReceiveProps or some way to invoke componentDidMount?
you can use componentDidUpdate() life cycle hooks.
and to get the route data in your component use this.props.match.params.folderId in that method
and to stop continuous call add if condition it will only call whenever route change.
I hope it will work!!
Related
I start with reactjs using reduxjs and react-router-dom
I have some route like main/route-1, main/route-2 ... And i want to call some api to get data in each router when user access or refresh. have any way to hanlder access router url to call special api with that router ? what best way to do that thank.
I don't know any way that you cant call API through the router. But you can call API when component loading. use axios to call the API inside the componentWillMount() function.
Edit: After I look again in documantation they mentioned that componentWillMount method is considered as legacy and don't use it. So you cant use componentDidMount it will call API immediately after the component mount. Their documentation also said that the componentDidMount is a good place for instantiating the network request.
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.
In react-router v4, onEnter was removed because of the new organization of the project, I get it.
But I used it to fetch data from the server before rendering the component.
It was suggested to use componentDidMount and fetch form there, this would work, but I use redux, and the code inside map(State|Dispatch)ToProps function expect the store to be up.
My current solution is to put some if's to check if it has data, and render empty, but that does not look to good...
Is there any documentation/example that I can see about using react-router v4 with redux?
Which is better?
I tried onEnter but that lead to flickering between paths. The onEnter check ran before the component was loaded. It routed and then re-routed after user was authenticated which was visually unpleasing. Now I'm just using Main component's componentWillMount lifecycle to run the authorization code and re-route if is resolved else stay there. If I use only lifecycle method to check then I can't use Link component from react-router. Any thoughts on how to solve the flickering or improve the client side security without crappy ui.
First of all you should do it in the componentDidMount and not on the componentWillMount since it can freeze the entire application if the process takes some time.
As for your problem, you can do the check in tje componentDidMount and then use react router's browserHistory to manually push the url.
Take a look at the histories docs of react router:
https://github.com/reactjs/react-router/blob/master/docs/guides/Histories.md
I am using react-router with the flux architecture (facebook's flux implementation).
Currently in my system I have route that says "chat/:topic".
When the user is entering this component, I am creating a subscription (using action creation, on componentWillMount) to a websocket server, and I am removing the subscription on componentWillUnmount.
When the user is moving to another route the whole workflow works alright - because react-router is unmounting my component.
When I transition inside my route (from "chat/games" to "chat/tv"), the component isn't mounted and I need to clear my state of the components.
I read about different actions that I can take and this on transition to dispatch an action "TRANSITION" and every relevant store will clear it's store.
In my opinion, this kind of action - is wrong, it couples my stores and my router.
How would you solve this problem? Is this an issue that I should raise to react-router and ask them to unmount inside my route?
I found the answer thanks to gaearon (https://github.com/gaearon/),
Use a store to keep the selected topic and ask the messages store for messages, in flux you shouldn't remove anything from your store, unless you need it for a performance reasons.
In my application, I must remove the messages (since they are large objects) and clear my subscriptions (to reduce the load on the server).
In order to achieve this there were three solutions that I found:
Use componentWillReceiveProps and check if the params are changed, if the params are changed - do whatever you need in order to clear the store - for example call ActionCreator and reset the state.
Send a dispose payload in transition (inside Router.run) which will tell all the stores to clear themselves.
last solution (which I used) making sure that my components are unmounted - Why? It is too error prone to clear the state on componentWillReceiveProps/dispose and it is clearer to just ensure the components are unmounted.
Details on how to achieve this:
https://github.com/rackt/react-router/issues/292
https://github.com/rackt/react-router/issues/496#issuecomment-64152941
I believe that compomentWillReceiveProps might solve your issue. This is what react router uses to pass stuff to you.
As far as I know, you need to use both componentWillReceiveProps AND componentDid/WillMount to catch the initial render also.
I'm anxiously awaiting the react-router 1.0 release (this weekend?) in hopes that there is a more elegant way to do this.