I'm working on extracting some code from my app into an open source package. Both my app and my package depend on the same version of React, 0.14.8.
Ever since I moved the code into the package (and made some code changes) I've been unable to render a component that uses refs. I've been searching for advice for hours, and it's yielded two basic tips:
- Make sure react versions aren't conflicting
- Make sure component with refs is created in another component's render method
As far as I can tell, I've satisfied both criteria.
class RangeQuery extends React.Component {
static propTypes = {
header: PropTypes.object.isRequired,
onQueryChange: PropTypes.func.isRequired
}
handleChange(ev) {
const { header } = this.props
const start = _.isEmpty(this.refs.start.value) ? null : this.refs.start.value
const end = _.isEmpty(this.refs.end.value) ? null : this.refs.end.value
const values = typeof(header.query.format) === 'function' ?
[header.query.fmtValue(start), header.query.fmtValue(end)] :
[start, end]
this.props.onQueryChange(header.field, header.query, values)
}
render() {
return (
<div>
<input className="form-control" type="text" ref="start" onChange={::this.handleChange} placeholder="min" />
<input className="form-control" type="text" ref="end" onChange={::this.handleChange} placeholder="max" />
</div>
)
}
}
const components = {
like: LikeQuery,
eq: EqQuery,
range: RangeQuery
}
export default class HeaderQuery extends React.Component {
static propTypes = {
header: PropTypes.object.isRequired,
onQueryChange: PropTypes.func.isRequired
}
render() {
const { header, onQueryChange } = this.props
const Query = components[header.query.type] || NoQuery
return (
<Query header={header} query={header.query} onQueryChange={this.props.onQueryChange} />
)
}
}
When I attempt to load the page with this component on it, I get the error:
invariant.js:39 Uncaught Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's
render
method, or you have multiple copies of React loaded
It renders if I remove the refs=
from the input
tags, but I obviously need those.
I have considered the alternative of writing a reducer to control the state of these components, but that's a heavy handed work around for something that should be working.
How can I fix my refs so that they'll work correctly?
Update
While I have accepted an answer on this question due to the fact that it allowed me to use refs like I wanted, the question still remains as to why it happened in the first place, and survey says the biggest suspect is multiple versions of react. As far as I can tell though, that doesn't seem to be the case.
sam@sam-macbook-ubuntu:~/myProject/client$ npm ls | grep react
├─┬ babel-preset-react@6.5.0
│ ├─┬ babel-plugin-transform-react-display-name@6.5.0
│ ├─┬ babel-plugin-transform-react-jsx@6.7.5
│ │ ├─┬ babel-helper-builder-react-jsx@6.7.5
│ └─┬ babel-plugin-transform-react-jsx-source@6.5.0
├─┬ react@0.14.8
├── react-addons-css-transition-group@0.14.8
├── react-addons-test-utils@0.14.8
├── react-dom@0.14.8
├─┬ react-loader@2.2.0
├─┬ react-redux@4.4.1
│ ├── hoist-non-react-statics@1.0.5
├── react-router@1.0.3
├─┬ react-select@1.0.0-beta12
│ └── react-input-autosize@0.6.10
│ ├─┬ react-json-tree@0.1.9
│ ├─┬ react-mixin@1.7.0
│ └── react-redux@3.1.2
│ └── react-lazy-cache@3.0.1