Skip to content

Commit

Permalink
Call setState on React components once per dispatch
Browse files Browse the repository at this point in the history
The current ReactMixin implementation calls `reactor.observe`
separately for each entry in the response to a React component's
getDataBindings. If multiple pieces of bound data change in a single
dispatch, Nuclear will call setState on the component for each of them
and React will dutifully render each time. This means that the exact
behavior of your component is dependent on the order in which you
define your data bindings (aside from being bad for performance).

This patch switches to a single `reactor.observe` call that includes
all of the data bindings for the component.

Fixes optimizely#193
  • Loading branch information
andrew-stripe committed Nov 17, 2015
1 parent 2e8b995 commit f0cdf53
Showing 1 changed file with 10 additions and 11 deletions.
21 changes: 10 additions & 11 deletions src/create-react-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,22 @@ export default function(reactor) {
},

componentDidMount() {
this.__unwatchFns = []
each(this.getDataBindings(), (getter, key) => {
const unwatchFn = reactor.observe(getter, (val) => {
this.setState({
[key]: val
})
})
const bindings = this.getDataBindings()
let keys = Object.keys(bindings)
const args = keys.map((k) => { return bindings[k] })
args.push((...vals) => { return vals })

this.__unwatchFns.push(unwatchFn)
this.__unwatchFn = reactor.observe(args, (vals) => {
let state = {}
each(vals, (val, i) => { state[keys[i]] = val })
this.setState(state)
})
},

componentWillUnmount() {
while (this.__unwatchFns.length) {
this.__unwatchFns.shift()()
if (this.__unwatchFn) {
this.__unwatchFn()
}
},
}
}

0 comments on commit f0cdf53

Please sign in to comment.