I am using react-router
and react-redux
. I have two routes like this:
<Route path='/edit' component={ EditNew } /> <Route path='/edit/:id' component={ EditDraft } />
where EditNew
and EditDraft
are data-providing containers that wrap an Editor
component using the react-redux
connect
function:
const EditNew = connect(state => ({}))(React.createClass({ render() { return <Editor />; } }));
and
const EditDraft = connect(state => ({ drafts: state.drafts }))(React.createClass({ render() { const { params, drafts } = this.props; const draft = findDraft(params.id, drafts); return <Editor draft={ draft } />; } }));
Now, Editor
is rigged up in such a way that when you begin typing into a blank Editor
, it triggers a history.replaceState()
from /edit
to /edit/:id
with a ranomly generated ID. When this happens, I get the following sequence of events:
EditorNew
unmountsEditor
unmountsEditorDraft
renders and mountsEditor
renders and mountsWhen I coded these two containers, I thought that the Editor
component contained in both of them would be reconciled without unmounting and remounting. This is problematic for me for several reasons besides the extra unnecessary work, chief among which are that the editor ends up losing focus and proper cursor range after the unmount and remount.
To no avail I have tried specifying key
for the Editor
component to hint to the reconciliation system that it's the same component, and I've tried shouldComponentUpdate
, but that doesn't get called, which makes sense given what React is doing.
Apart from combining the two containers into one container with more complicated render()
logic, is there anything I can do to prevent the Editor
component from unmounting/remounting during the history transition?
Using react-router you can easily prevent route change(which will prevent component unmount) by using Prompt . You need to manually pass the getUserConfirmation prop which is a function. You can modify this function as you like in any Router(Browser, Memory or Hash) to create your custom confirmation dialog(eg.
Don't Forget that Every Route Change Mounts and Unmounts a Component. Whenever you're using routing in a React application, you declare routes inside the Switch component. This means that only one component with the matching route is displayed at a time.
When rendering a function component, the state change causes the component to unmount and then remount. The same component using class based implementation won't unmount.
If it is “remounting” that means that it unmounted. You need to check into the docs of whatever nav you're using. If you can't do that, you'll have to find a way to preserve the data so you can repopulate it.
React’s Reconciliation Algorithm says that if the element has a different type (in this case, EditNew
and EditDraft
), then React will “tear down the old tree and build the new tree from scratch.”
To prevent this, you need to use the same component for both routes.
You can use shouldComponentUpdate
and, if the route has changed from /edit
to /edit/:id
(you can check this getting the router info from the state connected to your component) return false, so it won't refresh the component.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With