@@ -2,6 +2,7 @@ const hoistStatics = require('hoist-non-react-statics');
22const { Component, createElement } = require ( 'react' ) ;
33const PropTypes = require ( 'prop-types' ) ;
44const debounceFn = require ( 'lodash.debounce' ) ;
5+ const BackboneToReactContext = require ( './context' ) ;
56
67function getDisplayName ( name ) {
78 return `connectBackboneToReact(${ name } )` ;
@@ -70,9 +71,7 @@ module.exports = function connectBackboneToReact(
7071 constructor ( props , context ) {
7172 super ( props , context ) ;
7273
73- this . setModels ( props , context ) ;
74-
75- this . state = mapModelsToProps ( this . models , this . props ) ;
74+ this . componentIsMounted = false ;
7675
7776 this . createNewProps = this . createNewProps . bind ( this ) ;
7877 this . setWrappedInstance = this . setWrappedInstance . bind ( this ) ;
@@ -85,20 +84,24 @@ module.exports = function connectBackboneToReact(
8584 this . createEventListeners ( ) ;
8685 }
8786
88- setModels ( props , context ) {
89- const models = Object . assign ( { } , context . models , props . models ) ;
87+ getModels ( ) {
88+ const models = Object . assign ( { } , this . context , this . props . models ) ;
9089 validateModelTypes ( models ) ;
91- this . models = models ;
90+ return models ;
9291 }
9392
9493 createEventListeners ( ) {
95- Object . keys ( this . models ) . forEach ( mapKey => {
96- const model = this . models [ mapKey ] ;
94+ const models = this . getModels ( ) ;
95+ Object . keys ( models ) . forEach ( mapKey => {
96+ const model = models [ mapKey ] ;
9797 // Do not attempt to create event listeners on an undefined model.
9898 if ( ! model ) return ;
9999
100100 this . createEventListener ( mapKey , model ) ;
101101 } ) ;
102+
103+ // Store a reference to the models with event listeners for the next update.
104+ this . prevModels = models ;
102105 }
103106
104107 createEventListener ( modelName , model ) {
@@ -118,11 +121,11 @@ module.exports = function connectBackboneToReact(
118121 // The only case where this flag is encountered is when this component
119122 // is unmounted within an event handler but the 'all' event is still triggered.
120123 // It is covered in a test case.
121- if ( this . hasBeenUnmounted ) {
124+ // Also bails if we haven't yet mounted, to avoid warnings in strict mode.
125+ if ( ! this . componentIsMounted ) {
122126 return ;
123127 }
124-
125- this . setState ( mapModelsToProps ( this . models , this . props ) ) ;
128+ this . forceUpdate ( ) ;
126129 }
127130
128131 setWrappedInstance ( ref ) {
@@ -137,58 +140,57 @@ module.exports = function connectBackboneToReact(
137140 return this . wrappedInstance ;
138141 }
139142
140- UNSAFE_componentWillReceiveProps ( nextProps , nextContext ) { // eslint-disable-line camelcase
141- this . setModels ( nextProps , nextContext ) ;
142- this . createNewProps ( ) ;
143+ componentDidMount ( ) {
144+ this . componentIsMounted = true ;
145+ }
143146
144- // Bind event listeners for each model that changed.
145- Object . keys ( this . models ) . forEach ( mapKey => {
146- const model = this . models [ mapKey ] ;
147+ componentDidUpdate ( ) {
148+ // add and remove listeners
149+ const models = this . getModels ( ) ;
150+ const prevModels = this . prevModels ;
147151
148- // Retrieve old versions of the model from props and context for comparison.
149- const propsModel = this . props . models ? this . props . models [ mapKey ] : undefined ;
150- const contextModel = this . context . models ? this . context . models [ mapKey ] : undefined ;
152+ // Bind event listeners for each model that changed.
153+ Object . keys ( Object . assign ( { } , models , prevModels ) ) . forEach ( mapKey => {
154+ const model = models [ mapKey ] ;
155+ const prevModel = prevModels [ mapKey ] ;
151156
152157 // Do not attempt to create event listeners on an undefined model.
153158 if ( ! model ) {
154159 // Instead, if it was previously defined, remove the old listeners.
155- if ( propsModel ) {
156- this . removeEventListener ( mapKey , propsModel ) ;
157- // If a model with the matching mapKey exists in both props and context,
158- // we only remove listeners from the one in props. We do this because
159- // only the one in props is actually used in this.models, per the
160- // Object.assign in setModel.
161- } else if ( contextModel ) {
162- this . removeEventListener ( mapKey , contextModel ) ;
160+ if ( prevModel ) {
161+ this . removeEventListener ( mapKey , prevModel ) ;
163162 }
164163 return ;
165164 }
166165
167- if ( ( propsModel === model ) || ( contextModel === model ) ) return ; // Did not change.
166+ if ( prevModel === model ) return ; // Did not change.
168167
169168 this . createEventListener ( mapKey , model ) ;
170169 } ) ;
170+
171+ // Store a reference to the models with event listeners for the next update.
172+ this . prevModels = models ;
171173 }
172174
173175 componentWillUnmount ( ) {
174176 if ( debounce ) {
175177 this . createNewProps . cancel ( ) ;
176178 }
177179
178- Object . keys ( this . models ) . forEach ( mapKey => {
179- const model = this . models [ mapKey ] ;
180+ Object . keys ( this . prevModels ) . forEach ( mapKey => {
181+ const model = this . prevModels [ mapKey ] ;
180182 // Do not attempt to remove event listeners on an undefined model.
181183 if ( ! model ) return ;
182184 this . removeEventListener ( mapKey , model ) ;
183185 } ) ;
184186
185- this . hasBeenUnmounted = true ;
187+ this . componentIsMounted = false ;
186188 }
187189
188190 render ( ) {
189191 const wrappedProps = Object . assign (
190192 { } ,
191- this . state ,
193+ mapModelsToProps ( this . getModels ( ) , this . props ) ,
192194 this . props
193195 ) ;
194196
@@ -210,7 +212,7 @@ module.exports = function connectBackboneToReact(
210212 ConnectBackboneToReact . WrappedComponent = WrappedComponent ;
211213 ConnectBackboneToReact . displayName = displayName ;
212214 ConnectBackboneToReact . propTypes = propTypes ;
213- ConnectBackboneToReact . contextTypes = propTypes ;
215+ ConnectBackboneToReact . contextType = BackboneToReactContext ;
214216
215217 return hoistStatics ( ConnectBackboneToReact , WrappedComponent ) ;
216218 } ;
0 commit comments