Skip to content

Commit

Permalink
Merge pull request #170 from bitovi/dev/167-prop-updates
Browse files Browse the repository at this point in the history
begin prop update refactor
  • Loading branch information
Christopher Baker committed Jun 28, 2018
2 parents a45b45c + fa76736 commit 4a6ce40
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 13 deletions.
43 changes: 43 additions & 0 deletions derivers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import canDiff from 'can-diff';

function controlled(nextProps) {
// always use the latest props, overwiting existing data
return nextProps;
}

function uncontrolled(nextProps, lastProps) {
// use props on initial render (when lastProps is null)
if (lastProps === null) {
return nextProps;
}

// otherwise do nothing
return null;
}

function changes(nextProps, lastProps) {
// use props on initial render (when lastProps is null)
if (lastProps === null) {
return nextProps;
}

const patches = canDiff.map(lastProps, nextProps);
if (!patches.length) {
return null;
}

const diff = {};
for (const { key, type, value } of patches) {
if (type === 'set' || type === 'add') {
diff[key] = value;
}
}

return diff;
}

export {
controlled,
uncontrolled,
changes,
};
20 changes: 14 additions & 6 deletions lib/observable-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import canKey from 'can-key';
import { Object as ObservableClass } from 'can-observe';
import ObserverComponent from './observer-component';
import { createObservablePropsComponent } from './observable-props-component';
import { changes as deriveUpdatesChanges } from '../derivers';

class ObservableComponent extends ObserverComponent {
static ObservableClass = ObservableClass
static mapProps = (nextProps) => nextProps;
static deriveUpdates = deriveUpdatesChanges;

static getDerivedStateFromProps(nextProps, { observer, observable, mapProps, lastProps }) {
static getDerivedStateFromProps(nextProps, { observer, observable, deriveUpdates, lastProps }) {
if (nextProps !== lastProps) {
updateObservableWithProps(observable, mapProps(nextProps, lastProps), observer);
updateObservableWithProps(observable, deriveUpdates(nextProps, lastProps), observer);
}

return {
Expand All @@ -34,7 +35,8 @@ class ObservableComponent extends ObserverComponent {
this.state = {
observable: new this.constructor.ObservableClass(),
observer: this.observer,
mapProps: this.constructor.mapProps,
deriveUpdates: this.constructor.deriveUpdates,
lastProps: null,
};
}

Expand Down Expand Up @@ -109,10 +111,16 @@ function updateObservableWithProps(observable, newProps, observer) {
});
}

function createComponent(ObservableClass, { mapProps = props => props } = {}) {
function createComponent(ObservableClass, { deriveUpdates } = {}) {
if (deriveUpdates) {
return class YlemObservable extends ObservableComponent {
static ObservableClass = ObservableClass
static deriveUpdates = deriveUpdates
};
}

return class YlemObservable extends ObservableComponent {
static ObservableClass = ObservableClass
static mapProps = mapProps
};
}

Expand Down
12 changes: 5 additions & 7 deletions test/connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ QUnit.module('@connect with ObserveObject', () => {
foo = 'foo'
}

@connect(ViewModel, { mapProps: props => ({ props }) })
@connect(ViewModel, { deriveUpdates: props => ({ props }) })
class TestComponent extends Component {
static propTypes = {
foo: PropTypes.string.isRequired,
Expand Down Expand Up @@ -261,7 +261,7 @@ QUnit.module('@connect with ObserveObject', () => {
}).isRequired,
};

const ConnectedTestComponent = connect(ViewModel, { mapProps: props => ({ props }) })(TestComponent);
const ConnectedTestComponent = connect(ViewModel, { deriveUpdates: props => ({ props }) })(TestComponent);

if (process.env.NODE_ENV !== 'test-prod') {
supportsFunctionName && assert.equal(ConnectedTestComponent.name, 'YlemConnected(TestComponent)', 'returned component is properly named');
Expand Down Expand Up @@ -410,14 +410,12 @@ QUnit.module('@connect with ObserveObject', () => {
child11ViewModel.value = 'i';
assert.equal(getTextFromElement(parentDiv), 'ab!cd@e#fghi', 'ab!cd@e#fghi');

// Note: because parent re-rendered, child props overwrite change values in observable instance

parentViewModel.prop0 = 'A';
assert.equal(getTextFromElement(parentDiv), '01A23@4#5678', '01A23@4#5678');
assert.equal(getTextFromElement(parentDiv), 'abAcd@e#fghi', 'abAcd@e#fghi');
parentViewModel.prop1 = 'B';
assert.equal(getTextFromElement(parentDiv), '01A23B4#5678', '01A23B4#5678');
assert.equal(getTextFromElement(parentDiv), 'abAcdBe#fghi', 'abAcdBe#fghi');
parentViewModel.prop2 = 'C';
assert.equal(getTextFromElement(parentDiv), '01A23B4C5678', '01A23B4C5678');
assert.equal(getTextFromElement(parentDiv), 'abAcdBeCfghi', 'abAcdBeCfghi');

});
});

0 comments on commit 4a6ce40

Please sign in to comment.