Reputation: 12448
I am trying to select all the text in a textarea when a component loads using React v16.3.1
Following the Refs docs I have a basic sample but this.textarea
is always undefined, if I change this sample to execute the same code on a button click it works fine.
So whats going on? I had expected that after mounting the component should be available?
Sample code:
import React from "react";
class Hello extends React.Component {
constructor(props) {
super(props);
this.textarea = React.createRef();
}
componentDidMount = () => {
this.textarea.current.select();
};
render() {
return (
<div>
<textarea
className="form-control"
defaultValue="the quick brown fox."
ref={this.textarea}
/>
</div>
);
}
}
From package.json:
"react": "^16.3.1",
"react-dom": "^16.3.1",
Thanks
Upvotes: 8
Views: 7150
Reputation: 1850
For someone experiencing the same issue make sure that there's not another error somewhere in the stack that is causing a parent component to catch, for example.
class MyComponent extends React.Component {
private myRef = React.createRef();
constructor(props) {
super(props);
}
componentDidMount() {
console.log(this.myRef.current);
}
render() {
return (<div ref={this.myRef} />);
}
}
You may think that this.myRef will always be defined in this case but as it stands say you are using it like this
<SomeNewComponent>
<MyComponent />
</SomeNewComponent>
And some new component has an error of some sort during mounting... specially if it handles componentDidCatch and componentDidMount it will then make MyComponent's div never truly render.
It is odd that componentDidMount would be firing, but apparently it does; it's easy to overlook the stacktrace because all you see is the error from the myRef being null while the other one is way above in the console.
Upvotes: 0
Reputation: 204
The documentation says:
Note
The examples below have been updated to use the React.createRef() API introduced in React 16.3. If you are using an earlier release of React, we recommend using callback refs instead.
If you are using an earlier release of React, u need use callback refs
class App extends React.Component {
constructor(props) {
super(props);
this.textarea = null;
this.setTextareaRef = element => {
this.textarea = element;
};
}
componentDidMount = () => {
if (this.textarea) this.textarea.select();
};
render() {
return (
<div>
<textarea
className="form-control"
defaultValue="the quick brown fox."
ref={this.setTextareaRef}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
class App extends React.Component {
constructor(props) {
super(props);
this.textarea = React.createRef();
}
componentDidMount = () => {
this.textarea.current.select();
};
render() {
return (
<div>
<textarea
className="form-control"
defaultValue="the quick brown fox."
ref={this.textarea}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Upvotes: 3