I have started developing an app using Flux and react-router. One of my components populates using state obtained from a Flux store. This works fine. However when I navigate away from this component using react-router and then back again I get the above error. If I refresh the page the error goes away and the page works fine.
From my understanding of this it seems that react-router is not remounting this component so that it is trying to change the state of an unmounted component, hence the error.
If this is correct how do I get react-router to remount the component?
PS. The code for this is too long to post here It was posted on Github but since the problem has been solved now the post has been removed.
Update (thanks Sean):
The app can be run using the dist folder, just copy this folder to a webserver and point a browser to the folder (I am using xampp locally). The problem is on the week page (component TableWeekly runs this table). The problem occurs using the dropdown to change the view of lecturers. Works fine when first loaded or after a refresh but fails when you navigate to another page and back again.
Your problem is that you subscribe to change events in componentDidMount, but never unsubscribe on componentWillUnmount. In other words, every time a TableWeekly component is mounted, a new event handler is attached but never detached when that component unmounts.
When MainStore emits a change event, it will call the _onChange event handler on an unmounted component, which in turn will try to update state and produce an invariant error.
To fix this, add the following componentWillUnmount method to your TableWeekly and DropdownWeekly
componentWillUnmount: function() {
MainStore.removeChangeListener(this._onChange);
}
Related
I am able to change state of App from webcomponent and get initial state using recoil-nexus package. But unable to get changing state. For eg- changed state after state is mutated in webcomponent or in app.
As RecoilRoot internally uses react's context API and Webcomponent (shadowDOM) creates new React tree which do not have access to context of the RecoilRoot. How to get changing state in webcomponent of the atom in App?
Webcomponent reference - https://reactjs.org/docs/web-components.html,
Failed attempts:
Tried creating custom hook to get recoil state after useRecoilSnapshot changes.
Tried Hook rerun on reference of nexus.get change.
Tried attaching custom state to window using useRecoilTransactionObserver_UNSTABLE(callback).
Tried recoil-outside which uses rxjs to observe state.
Tried recoil-sync but did not received event in 'write' event handler prop in webcomponent. It only works inside RecoilRoot and not outside.
getRecoilPromise might work but how to use async at top level of the component? Tried in useEffect but it did not work for me.
Nothing seems to refresh state in webcomponent.
Alternate Queries:
How to sync snapshot between two different RecoilRoot (which are not nested)?
React component tree in dev tool -
Does Reloading of react app i.e not implementing will remove all the saved state in our react app
Edit:
To be more specific ,
The question was what will happen to the child components state when its parent component gets reloaded i.e whether the state will be removed or not
Your question is a bit vague, but it depends:
If you are reloading your entire react app then yes, all your states will be lost. You can however persist data using localStorage in most cases.
If you are reloading a component from your app, you can save state using useEffect, or by using react class components rather than functional components and use the componenetDidUpdate function to catch updates. Additionally componentDidMount can help you recognise when a component is re-rendered and use it to read persisted data from localStorage
If your component is within another component that does reload then yes it will also reload and state will be lost.
You can read more about the component life-cycle in the react-docs but they don't really touch on it.
The simple Code Sandbox below shows that navigating to a component triggers a fresh render. The React profiler states the components were rendered because they are continually seen for the first time. I understand this to be the correct React behavior, because each mounting/render generates new method references that triggers the re-rendering. However, this means that several http requests will be made despite nothing having changed. Is there any way to keep those requests from being made every time the user navigates to a component?
In the codesandbox I've tried using React.memo along with useCallback, and neither reuse the initial rendering.
Click the console tab to see each time the component renders, it makes a fresh ajax call.
https://codesandbox.io/s/github/pstephenwille/react-render-question
To avoid redundant HTTP calls you have to verify that your origin server does not have updated your local data. If you really want to just fire the HTTP calls once, you can e.g. execute them in your App component or pass a state and a callback function down to your Foo and Bar screen components that will ensure a singular call
I want to fire a function when all scripts are loaded in my react app. My app uses hot loaders (react-hot-loader). How do fire some event when all script on a page are loaded and executed. Thank you!
I load the modules/components like:
export const Root = hot(RootUnwrapped);
If we looking in documentation we see:
(that's the goal) React-Hot-Loader would not change the past, only
update the present - no lifecycle event would be called on component
update. As a result - all the code changes, you may made among
componentWillUnmount or componentDidMount, would be ignored for
already created components.
(that's the goal) React-Hot-Loader would not update any object,
including component state.
But, as we know, hot loader resets state.
So, you can get one of lifecycle methods that allows you to check old and new state.
If the state is reset to the init state, it was Hot-Loader.
P.S. But, if your goal is check when your app is first loaded, you can do it in constructor of root component.
I have an issue with my app that I cannot find solution for anywhere. I use react-router-redux and syncHistoryWithStore.
When I click on my navigation to change a route using Link the new route loads, URL in the browser updates, however the location state doesn't update unless I click the Link two times.
UPDATE:
I've noticed it might have something to do with Chrome React DevTools. If I open the React Devtools and select provider then unwrap the components tree one at a time, the location state updates and everything works fine. However, if I use the search bar to locate the target component, location state doesn't work any more and the app breaks. Weird?!
Has anyone encountered a similar issue before? Any idea how to fix this?