Skip to content

Commit 23d0c4a

Browse files
committed
0.3.1: added component.isMounted()
1 parent 69a2b47 commit 23d0c4a

File tree

8 files changed

+40
-10
lines changed

8 files changed

+40
-10
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# 0.3
22

3+
## 0.3.1
4+
5+
### Added `component.isMounted()` API
6+
7+
As we roll out increased support for dynamic mounting, knowing whether or not a component is currently mounted becomes increasingly relevant. In previous versions this could be checked by looking for the `__mounted` internal variable on the component instance (which is now deprecated)
8+
9+
There is now a `component.isMounted()` API which returns true when the component is mounted and false otherwise.
10+
11+
## 0.3.0
12+
313
### **BREAKING CHANGE:** New component mounting API
414

515
In light of the architectural changes in 0.2, and because the old API was quite confusing, we've designed a new API for mounting components. The `mounter` function has been eliminated and replaced with an imperative API for mounting and unmounting.

docs/API/Components.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ this.componentWillUnmount = =>
4242
Invoked on a component instance immediately before its reducer is removed from the state tree.
4343
> When multiple nodes are unmounted simultaneously, their ```componentWillUnmount()``` methods are called in postorder with respect to their place in the state tree. (leaf nodes first)
4444
45+
#### isMounted
46+
```coffeescript
47+
this.isMounted = => boolean
48+
```
49+
Returns `true` if the component's reducer is mounted to the Redux store, `false` otherwise.
50+
4551
### Redux state
4652

4753
#### this.state

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "redux-components",
3-
"version": "0.3.0",
3+
"version": "0.3.1",
44
"description": "A component model for Redux state trees based on the React.js component model.",
55
"keywords": [
66
"redux",

src/ReduxComponent.coffee

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,24 @@ ReduxComponent.prototype.updateReducer = ->
1919
if process.env.NODE_ENV isnt 'production'
2020
invariant(typeof @getReducer is 'function', "redux-component of type #{@displayName} (mounted at location #{@path}) is updating its reducer, but does not have a getReducer() method.")
2121
@__internalReducer = @getReducer(@state)
22+
undefined
2223

2324
ReduxComponent.prototype.__willMount = (@store, @path = [], @parentComponent = null) ->
2425
invariant(not @__mounted, "redux-component of type #{@displayName} was multiply initialized. This can indicate a cycle in your component graph, which is illegal. Make sure each instance is only used once in your tree. If you wish to use a component in multiple places, construct additional instances.")
25-
@__mounted = true
2626
@componentWillMount?()
2727
#@reducer = indirectReducer.bind(@)
2828
@updateReducer()
29+
undefined
30+
31+
ReduxComponent.prototype.__didMount = ->
32+
@__mounted = true
33+
@componentDidMount?()
34+
undefined
2935

3036
ReduxComponent.prototype.__willUnmount = ->
3137
invariant(@__mounted, "redux-component of type #{@displayName} was unmounted when not mounted. This can indicate an issue in a dynamic reducer component such as redux-components-map.")
3238
@componentWillUnmount?()
3339
@__internalReducer = nullIdentity
3440
delete @__mounted
41+
42+
ReduxComponent.prototype.isMounted = -> @__mounted?

src/mountComponent.coffee

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
export mountRootComponent = (store, componentInstance) ->
2-
componentInstance.__willMount(store, [], null)
3-
store.replaceReducer(componentInstance.reducer)
4-
componentInstance.componentDidMount?()
5-
61
export willMountComponent = (store, componentInstance, path) ->
72
componentInstance.__manualMount = true
83
componentInstance.__willMount(store, path, null)
94
componentInstance.reducer
105

116
export didMountComponent = (componentInstance) ->
12-
componentInstance.componentDidMount?()
7+
componentInstance.__didMount()
138

149
export willUnmountComponent = (componentInstance) ->
1510
componentInstance.__willUnmount()
11+
12+
export mountRootComponent = (store, componentInstance) ->
13+
reducer = willMountComponent(store, componentInstance, [])
14+
store.replaceReducer(reducer)
15+
didMountComponent(componentInstance)

src/subtree.coffee

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import createClass from './createClass'
66

77
##### SubtreeMixin
88
attachComponent = (parentComponent, key, component) ->
9-
# XXX: invariant or warning here that key is not shadowing anything on the instance?
9+
# Development invariant: prevent shadowing of parent keys
10+
if process.env.NODE_ENV isnt 'production'
11+
invariant(not parentComponent[key]?, "redux-component of type #{parentComponent.displayName} (mounted at location #{parentComponent.path}) is using SubtreeMixin, and one of its children would shadow the key `#{key}` on the parent component.")
1012
parentComponent[key] = component
1113
childPath = parentComponent.path.concat( [ key ] )
1214
component.__willMount(parentComponent.store, childPath, parentComponent)
@@ -35,7 +37,7 @@ export SubtreeMixin = {
3537
# Monkey-patch didMount to call subtree didMounts in the right order.
3638
myDidMount = @__originalDidMount = @componentDidMount
3739
@componentDidMount = ->
38-
@[k]?.componentDidMount?() for k of __reducerMap
40+
@[k]?.__didMount() for k of __reducerMap
3941
myDidMount?.call(@)
4042

4143
componentWillUnmount: ->

test/01-basic.coffee

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ describe 'basic functions: ', ->
2626
it 'should mount instance of class on store', ->
2727
rootComponentInstance = new Subcomponent()
2828
mountRootComponent(store, rootComponentInstance)
29+
expect(rootComponentInstance.isMounted()).to.be.ok
2930

3031
it 'should know about the store', ->
3132
expect(rootComponentInstance.store).to.equal(store)
@@ -60,7 +61,9 @@ describe 'basic functions: ', ->
6061

6162
it 'should mount instance of class on store', ->
6263
rootComponentInstance = new Subcomponent()
64+
expect(rootComponentInstance.isMounted()).to.not.be.ok
6365
mountRootComponent(store, rootComponentInstance)
66+
expect(rootComponentInstance.isMounted()).to.be.ok
6467

6568
it 'should set the default state', ->
6669
expect(store.getState()).to.deep.equal({})

test/02-subtree.coffee

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ describe 'subtree: ', ->
7777
it 'should instantiate class keys on subtree', ->
7878
assert(not(Subcomponent instanceof Subcomponent))
7979
assert(rootComponentInstance.bar instanceof Subcomponent)
80+
assert(rootComponentInstance.bar.isMounted())
8081

8182
it 'should scope actions and selectors', ->
8283
store.dispatch(rootComponentInstance.foo.setValue('foo'))

0 commit comments

Comments
 (0)