Skip to content

Commit e1a9132

Browse files
committed
fix(API): API Updates
Queries now accept named parameters. Guards have been added to see if any passed in props clash with props that are resolved via the queries.
1 parent def81a3 commit e1a9132

File tree

3 files changed

+57
-15
lines changed

3 files changed

+57
-15
lines changed

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,13 @@ class MyComponent extends Component {
3232

3333
export default ComponentQueries(
3434
// Provide as many query functions as you need.
35-
(width) => width <= 330 ? { scale: 'mobile' } : {},
36-
(width) => width > 330 && width <=960 ? { scale: 'tablet' } : {},
37-
(width) => width > 960 && width <=1024 ? { scale: 'desktop' } : {},
35+
({ width }) => width <= 330 ? { scale: 'mobile' } : {},
36+
({ width }) => width > 330 && width <=960 ? { scale: 'tablet' } : {},
37+
({ width }) => width > 960 ? { scale: 'desktop' } : {},
38+
// Pass in height too
39+
({ height }) => height > 200 ? { short: false } : { short: true },
40+
// Or both
41+
({ width, height }) => width === height ? { square: true } : { square: false },
3842
)(MyComponent);
3943
```
4044

src/ComponentQueries.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,6 @@ function ComponentQueries(...queries) {
2020
`All provided queries for ComponentQueries should be functions.`
2121
);
2222

23-
function query(width, height) {
24-
return queries.reduce((acc, cur) =>
25-
Object.assign({}, acc, cur(width, height))
26-
, {});
27-
}
28-
2923
return function WrapComponent(WrappedComponent) {
3024
class ComponentWithComponentQueries extends Component {
3125
state = {
@@ -55,12 +49,28 @@ function ComponentQueries(...queries) {
5549
}
5650

5751
runQueries({ width, height }) {
58-
const queryResult = query(width, height);
52+
const queryResult = queries.reduce((acc, cur) =>
53+
Object.assign({}, acc, cur({ width, height }))
54+
, {});
5955

6056
this.setState({ queryResult });
6157
}
6258

59+
checkForDuplicateProps() {
60+
const provided = new Set(Object.keys(this.props));
61+
62+
Object.keys(this.state.queryResult).forEach(queryProp =>
63+
invariant(
64+
!provided.has(queryProp),
65+
`Duplicate prop has been provided to Component with ComponentQueries: ${queryProp}`)
66+
);
67+
}
68+
6369
render() {
70+
// We need this guard to execute here in order to guarantee we have
71+
// both the updated state and the passed in props.
72+
this.checkForDuplicateProps();
73+
6474
const { size, ...otherProps } = this.props; // eslint-disable-line no-unused-vars
6575

6676
return (

test/ComponentQueries.test.js

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,49 @@ describeWithDOM(`Given the ComponentQueries library`, () => {
4343
let receivedProps;
4444

4545
const ComponentQueriedComponent = ComponentQueries(
46-
(width) => width <= 100 ? { foo: `bar` } : {},
47-
(width) => width > 100 && width <= 500 ? { bob: `baz` } : {}
46+
({ width }) => width <= 100 ? { foo: `bar` } : {},
47+
({ width }) => width > 100 && width <= 500 ? { bob: `baz` } : {},
48+
({ height }) => height <= 100 ? { zip: `zap` } : {}
4849
)((props) => { receivedProps = props; return <div></div>; });
4950

5051
// Initial render
5152
const mounted = mount(<ComponentQueriedComponent size={{ width: 100, height: 100 }} />);
52-
expect(receivedProps).to.eql({ foo: `bar` });
53+
expect(receivedProps).to.eql({ foo: `bar`, zip: `zap` });
5354

5455
// Update size, but no size change
5556
mounted.setProps({ size: { width: 100, height: 100 } });
56-
expect(receivedProps).to.eql({ foo: `bar` });
57+
expect(receivedProps).to.eql({ foo: `bar`, zip: `zap` });
5758

5859
// Update size, with change.
59-
mounted.setProps({ size: { width: 101, height: 100 } });
60+
mounted.setProps({ size: { width: 101, height: 99 } });
61+
expect(receivedProps).to.eql({ bob: `baz`, zip: `zap` });
62+
63+
// Update size, with change.
64+
mounted.setProps({ size: { width: 101, height: 101 } });
6065
expect(receivedProps).to.eql({ bob: `baz` });
6166
});
67+
68+
it(`Then it should throw an error when a duplicate prop is provided`, () => {
69+
const ComponentQueriedComponent = ComponentQueries(
70+
({ width }) => width <= 100 ? { foo: `bar` } : {}
71+
)(() => <div></div>);
72+
73+
// Initial render duplicate prop
74+
const onMount = () => mount(
75+
<ComponentQueriedComponent foo="foo" size={{ width: 100, height: 100 }} />
76+
);
77+
78+
expect(onMount).to.throw(/Duplicate prop has been provided/);
79+
80+
// Updated component duplicate prop
81+
const mounted = mount(
82+
<ComponentQueriedComponent size={{ width: 100, height: 100 }} />
83+
);
84+
85+
const updateComponent = () =>
86+
mounted.setProps({ foo: `baz` });
87+
88+
expect(updateComponent).to.throw(/Duplicate prop has been provided/);
89+
});
6290
});
6391
});

0 commit comments

Comments
 (0)