I'm trying to focus()
a conditionally rendered textarea in React. The code below is almost exactly identical to the example in the React docs or to this similar question.
The code below immediately shows and focuses the textarea. If the three mented lines are unmented, the textarea gets shown after the condition
prop is set to true
(its value depends on the state of the parent and is initially false
), but the element doesn't get focused anymore.
If the condition is initially true
, the input element gets focused as expected when the ponent renders for the first time. The problem occurs when the condition is changed from false
to true
.
import React, { Component } from 'react'
class TestClass extends Component {
constructor(props) {
super(props)
this.focus = this.focus.bind(this)
}
ponentDidMount() {
// this.props.condition &&
this.focus()
}
ponentDidUpdate() {
// this.props.condition &&
this.focus()
}
focus() {
console.log(`this.textInput: ${this.textInput}`)
this.textInput.focus()
}
render() {
return (
<div>
{
// this.props.condition &&
<textarea
ref={(input) => {this.textInput = input}}
defaultValue="Thanks in advance for your invaluable advice">
{console.log('textarea rendered')}
</textarea>
}
</div>
)
}
}
The console output
textarea rendered
this.textInput: [object HTMLTextAreaElement]
rules out that the element is unavailable at the time focus()
gets executed.
Furthermore:
- Setting
autoFocus
attribute doesn't seem to work, in contrast to this question - Same problem for both
<input />
and<textarea />
Edit: in response to the question below, the parent ponent looks as follows.
class ParentComponent extends Component {
constructor(props) {
super(props)
this.state = {
condition: false
}
this.toggleCondition = this.toggleCondition.bind(this)
}
toggleCondition() {
this.setState(prevState => ({
condition: !prevState.condition
}))
}
render() {
return (
<div>
<TestClass condition={this.state.condition} />
<button onMouseDown={this.toggleCondition} />
</div>
)
}
}
I'm trying to focus()
a conditionally rendered textarea in React. The code below is almost exactly identical to the example in the React docs or to this similar question.
The code below immediately shows and focuses the textarea. If the three mented lines are unmented, the textarea gets shown after the condition
prop is set to true
(its value depends on the state of the parent and is initially false
), but the element doesn't get focused anymore.
If the condition is initially true
, the input element gets focused as expected when the ponent renders for the first time. The problem occurs when the condition is changed from false
to true
.
import React, { Component } from 'react'
class TestClass extends Component {
constructor(props) {
super(props)
this.focus = this.focus.bind(this)
}
ponentDidMount() {
// this.props.condition &&
this.focus()
}
ponentDidUpdate() {
// this.props.condition &&
this.focus()
}
focus() {
console.log(`this.textInput: ${this.textInput}`)
this.textInput.focus()
}
render() {
return (
<div>
{
// this.props.condition &&
<textarea
ref={(input) => {this.textInput = input}}
defaultValue="Thanks in advance for your invaluable advice">
{console.log('textarea rendered')}
</textarea>
}
</div>
)
}
}
The console output
textarea rendered
this.textInput: [object HTMLTextAreaElement]
rules out that the element is unavailable at the time focus()
gets executed.
Furthermore:
- Setting
autoFocus
attribute doesn't seem to work, in contrast to this question - Same problem for both
<input />
and<textarea />
Edit: in response to the question below, the parent ponent looks as follows.
class ParentComponent extends Component {
constructor(props) {
super(props)
this.state = {
condition: false
}
this.toggleCondition = this.toggleCondition.bind(this)
}
toggleCondition() {
this.setState(prevState => ({
condition: !prevState.condition
}))
}
render() {
return (
<div>
<TestClass condition={this.state.condition} />
<button onMouseDown={this.toggleCondition} />
</div>
)
}
}
Share
Improve this question
edited Jul 24, 2017 at 10:59
Bart
asked Jul 24, 2017 at 9:05
BartBart
1,6092 gold badges14 silver badges29 bronze badges
10
-
If you substitute your
this.props.condition &&
for a more verboseif(this.props.condition) { }
in both ponentDidMount and ponentDidUpdate does this change the behaviour in any way? – Finbarr O'B Commented Jul 24, 2017 at 9:21 -
Unfortunately, no. In JavaScript,
true && expression
always evaluates toexpression
, andfalse && expression
always evaluates tofalse
. (Source: facebook.github.io/react/docs/…) – Bart Commented Jul 24, 2017 at 9:25 -
Can you add your parent ponent code which is adding the TestClass ponent? I think the problem may lie in how you are passing 'condition' as a prop, if I pass it as a string using
<TestClass condition="true"/>
, it doesn't work, however passing condition as a boolean flag works for me:<TestClass condition/>
– Finbarr O'B Commented Jul 24, 2017 at 9:36 -
My guess is that the problem lies with the condition being initially
false
. If I set the condition to be initiallytrue
, it works. The condition is a boolean, but I will post the parent class in a minute. – Bart Commented Jul 24, 2017 at 9:40 -
I've tested your code in playground.
TestClass
updates properly as you expect.this.focus
executes on every toggling. Maybe I got something wrong and didn't get the question. Can you provides some other details? – Slowyn Commented Jul 24, 2017 at 10:22
2 Answers
Reset to default 3import React, { Component } from 'react';
class TestClass extends Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
ponentDidMount() {
this.focus();
}
ponentWillReceiveProps(nextProps) {
if (nextProps.condition !== this.props.condition) {
this.focus();
}
}
focus() {
console.log(`this.textInput: ${this.textInput}`);
if (this.props.condition === true) {
this.textInput.focus();
}
}
render() {
return (
<div>
{
this.props.condition &&
<textarea
ref={(input) => { this.textInput = input; }}
defaultValue="Thanks in advance for your invaluable advice"
>
{console.log('textarea rendered')}
</textarea>
}
</div>
);
}
}
export default TestClass;
Turns out the problem was really really stupid. The way I implemented the toggle button (which I simplified to <button onClick={this.toggleCondition} />
in the original question "for clarity"), was with a custom ponent which takes the onClick
prop and attaches its value to the onMouseDown
attribute of a hyperlink.
Because the hyperlink gets focused after its onMouseDown
action, the focus was immediately taken away from the textarea.
I've edited the question to reflect my usage of onMouseDown
.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744219610a4563717.html
评论列表(0条)