-
Notifications
You must be signed in to change notification settings - Fork 116
Multiple Queries #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple Queries #39
Changes from 6 commits
a0665e8
8975a19
02fce3c
5d0787c
1633031
db44433
59bc446
04dc600
bf347a5
3cd10c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,14 @@ class Media extends React.Component { | |
PropTypes.string, | ||
PropTypes.object, | ||
PropTypes.arrayOf(PropTypes.object.isRequired) | ||
]).isRequired, | ||
]), | ||
queries: PropTypes.shape({ | ||
[PropTypes.string]: PropTypes.oneOfType([ | ||
PropTypes.string, | ||
PropTypes.object, | ||
PropTypes.arrayOf(PropTypes.object.isRequired) | ||
]), | ||
}), | ||
render: PropTypes.func, | ||
children: PropTypes.oneOfType([ | ||
PropTypes.node, | ||
|
@@ -22,37 +29,75 @@ class Media extends React.Component { | |
matches: true | ||
} | ||
|
||
updateMatches = () => | ||
this.setState({ matches: this.mediaQueryList.matches }) | ||
updateMatches = () => { | ||
let { query, queries } = this.props | ||
if (query) | ||
this.setState({ | ||
matches: this.mediaQueryList.reduce((accumulated, { name, mm }) => ({ | ||
...accumulated, | ||
[name]: mm.matches, | ||
}), {}).match, | ||
}) | ||
|
||
if (queries) | ||
this.setState({ | ||
matches: this.mediaQueryList.reduce((accumulated, { name, mm }) => ({ | ||
...accumulated, | ||
[name]: mm.matches, | ||
}), {}), | ||
}) | ||
} | ||
|
||
componentWillMount() { | ||
if (typeof window !== 'object') | ||
return | ||
|
||
let { query } = this.props | ||
let { query, queries } = this.props | ||
|
||
if (typeof query !== 'string') | ||
if (query && typeof query !== 'string') | ||
query = json2mq(query) | ||
|
||
this.mediaQueryList = window.matchMedia(query) | ||
this.mediaQueryList.addListener(this.updateMatches) | ||
if (query) { | ||
this.mediaQueryList = [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an array that we created. It's not really a MediaQueryList, just something we made to hold a bunch of media queries. Let's call it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. makes sense, updated |
||
{ | ||
name: 'match', | ||
mm: window.matchMedia(query), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The object returned from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I opted for |
||
} | ||
] | ||
} | ||
|
||
if (queries) { | ||
queries = Object.keys(queries).map(mq => ({ | ||
name: mq, | ||
qs: json2mq(queries[mq]), | ||
})) | ||
this.mediaQueryList = queries.map(mq => ({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the case of a single query, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. understood and updated. Thanks! |
||
name: mq.name, | ||
mm: window.matchMedia(mq.qs), | ||
})) | ||
} | ||
|
||
this.mediaQueryList.map(ql => ql.mm.addListener(this.updateMatches)) | ||
this.updateMatches() | ||
} | ||
|
||
componentWillUnmount() { | ||
this.mediaQueryList.removeListener(this.updateMatches) | ||
let { query, queries } = this.props | ||
if (query || queries) | ||
this.mediaQueryList.map(ql => ql.mm.removeListener(this.updateMatches)) | ||
} | ||
|
||
render() { | ||
const { children, render } = this.props | ||
const { children, render, queries, query } = this.props | ||
const { matches } = this.state | ||
|
||
return ( | ||
render ? ( | ||
matches ? render() : null | ||
) : children ? ( | ||
typeof children === 'function' ? ( | ||
children(matches) | ||
query && children(matches) || | ||
queries && children({ ...matches }) | ||
) : !Array.isArray(children) || children.length ? ( // Preact defaults to empty children array | ||
matches ? React.Children.only(children) : null | ||
) : ( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't valid. You can't use
PropTypes.string
as the key of an object because it will just be converted to a string. Instead, let's use:To reduce on code duplication, let's also create a type for the
oneOfType
and call itqueryType
.Then we can reuse that in both
propTypes.query
andpropTypes.queries
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
understood, I've been using
flow
too much 🙊