Skip to content

Commit 80ac065

Browse files
committed
0.3.3:
- SubtreeMixin changes - Support dynamic mounting and unmounting - Add `subtreeReducer` field - Refactor internals
1 parent afda6f5 commit 80ac065

File tree

4 files changed

+55
-19
lines changed

4 files changed

+55
-19
lines changed

CHANGELOG.md

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

3+
## 0.3.3
4+
5+
### SubtreeMixin changes
6+
7+
The new mounting system enabled a cleanup of the `SubtreeMixin` internals, including the removal of the `didMount` monkey patch. This should not be a breaking change for those following the API, but may break code relying on subtree internals.
8+
9+
- `SubtreeMixin` components now support dynamic mounting. (Meaning that the `SubtreeMixin` component can be dynamically mounted, not that its contents can change dynamically -- please use `redux-components-map` if you need that functionality.)
10+
11+
- A new documented field, `this.subtreeReducer`, exists on all `SubtreeMixin` component instances. This is the reducer obtained by `combineReducers` over the subcomponents. Using this functionality, it is now possible to write custom reducers for `SubtreeMixin` components that fallback on the combined reducer when they don't understand an action.
12+
13+
- The `__reducerMap` and `__originalDidMount` undocumented fields no longer exist.
14+
15+
### Miscellaneous
16+
17+
- The `Object.assign` polyfill has been removed. Your runtime must support `Object.assign` natively, or you must polyfill it yourself.
18+
319
## 0.3.2
420

521
### Observable selector changes

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# redux-components
22
A component model for Redux state trees based on the React.js component model and other familiar design patterns from the React ecosystem.
33

4+
## What's New
5+
6+
- We've been making a lot of great improvements. Check out the [Change Log](CHANGELOG.md) for details -- particularly if you are moving to a higher significant version digit!
7+
8+
- Check out [redux-components-map](https://github.com/wcjohnson/redux-components-map) for a solution to a common use case: dynamic tree structure changes while your app is running.
9+
410
## Documentation
511
> **NB:** redux-components is a tool that interoperates with [Redux](http://redux.js.org/). This documentation presumes a solid grasp of the fundamentals found in the [Redux docs](http://redux.js.org) -- particularly the concepts of the Redux state tree, reducers, action creators, and selectors.
612

src/subtree.coffee

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { combineReducers } from 'redux'
22
import invariant from 'invariant'
33
import ReduxComponent from './ReduxComponent'
44
import createClass from './createClass'
5-
5+
import { willMountComponent, didMountComponent, willUnmountComponent } from './mountComponent'
66

77
##### SubtreeMixin
88
attachComponent = (parentComponent, key, component) ->
@@ -12,36 +12,37 @@ attachComponent = (parentComponent, key, component) ->
1212
parentComponent[key] = component
1313
childPath = parentComponent.path.concat( [ key ] )
1414
component.__willMount(parentComponent.store, childPath, parentComponent)
15-
# Return the reducer
16-
component.reducer
15+
component
1716

1817
applyDescriptor = (parentComponent, key, descriptor) ->
1918
attachComponent(parentComponent, key, createComponent(descriptor))
2019

2120
export SubtreeMixin = {
21+
getReducer: -> @subtreeReducer
22+
2223
componentWillMount: ->
2324
# Sanity check that our component supports subtrees
2425
if process.env.NODE_ENV isnt 'production'
2526
invariant(typeof @getSubtree is 'function', "redux-component of type #{@displayName} (mounted at location #{@path}) is using SubtreeMixin, but does not have a getSubtree() method.")
2627

27-
# Get the subtree structure
28-
subtree = @getSubtree()
29-
# Conjure child components and gather their reducers
30-
__reducerMap = {}
31-
for key, descriptor of subtree
32-
__reducerMap[key] = applyDescriptor(@, key, descriptor)
33-
# Create composite reducer for parent component
34-
reducer = combineReducers(__reducerMap)
35-
@getReducer = -> reducer
28+
# Create subcomponents
29+
@__subtree = {}
30+
for key, descriptor of @getSubtree()
31+
@__subtree[key] = applyDescriptor(@, key, descriptor)
32+
33+
# Create reducer
34+
reducerMap = {}
35+
for key, component of @__subtree
36+
reducerMap[key] = component.reducer
37+
@subtreeReducer = combineReducers(reducerMap)
3638

37-
# Monkey-patch didMount to call subtree didMounts in the right order.
38-
myDidMount = @__originalDidMount = @componentDidMount
39-
@componentDidMount = ->
40-
@[k]?.__didMount() for k of __reducerMap
41-
myDidMount?.call(@)
39+
componentDidMount: ->
40+
didMountComponent(component) for key, component of @__subtree
41+
undefined
4242

4343
componentWillUnmount: ->
44-
@componentDidMount = @__originalDidMount
44+
willUnmountComponent(component) for key, component of @__subtree
45+
undefined
4546
}
4647

4748
##### createComponent

src/test/02-subtree.test.coffee

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{ inspect } = require 'util'
22

33
{ expect, assert } = require 'chai'
4-
{ createClass, mountRootComponent, createComponent, SubtreeMixin } = require '..'
4+
{ createClass, mountRootComponent, createComponent, SubtreeMixin, willUnmountComponent } = require '..'
55
{ makeAStore } = require './helpers/store'
66

77
describe 'subtree: ', ->
@@ -20,6 +20,8 @@ describe 'subtree: ', ->
2020
console.log "Subcomponent.willMount"
2121
componentDidMount: ->
2222
console.log "Subcomponent.didMount"
23+
componentWillUnmount: ->
24+
console.log "Subcomponent.willUnmount"
2325
getReducer: -> (state = {}, action) ->
2426
switch action.type
2527
when @SET then action.payload or {}
@@ -50,7 +52,15 @@ describe 'subtree: ', ->
5052
componentWillMount: ->
5153
console.log "RootComponent.willMount"
5254
componentDidMount: ->
55+
assert(@foo.isMounted())
56+
assert(@bar.isMounted())
57+
assert(@deep.isMounted())
5358
console.log "RootComponent.didMount"
59+
componentWillUnmount: ->
60+
assert(not @foo.isMounted())
61+
assert(not @bar.isMounted())
62+
assert(not @deep.isMounted())
63+
console.log "RootComponent.willUnmount"
5464
getSubtree: -> {
5565
foo: new Subcomponent()
5666
bar: Subcomponent
@@ -86,3 +96,6 @@ describe 'subtree: ', ->
8696
expect(rootComponentInstance.foo.getValue()).to.equal('foo')
8797
expect(rootComponentInstance.bar.getValue()).to.equal('bar')
8898
expect(rootComponentInstance.deep.zazz.getValue()).to.equal('deep.zazz')
99+
100+
it 'should unmount correctly', ->
101+
willUnmountComponent(rootComponentInstance)

0 commit comments

Comments
 (0)