Reputation: 4510
Is it possible to focus div (or any other elements) using the focus()
method?
I've set a tabIndex to a div element:
<div ref="dropdown" tabIndex="1"></div>
And I can see it gets focused when I click on it, however, I'm trying to dynamically focus the element like this:
setActive(state) {
ReactDOM.findDOMNode(this.refs.dropdown).focus();
}
Or like this:
this.refs.dropdown.focus();
But the component doesn't get focus when the event is triggered. How can I do this? Is there any other (not input) element I can use for this?
EDIT:
Well, It seems this it actually possible to do: https://jsfiddle.net/69z2wepo/54201/
But it is not working for me, this is my full code:
class ColorPicker extends React.Component {
constructor(props) {
super(props);
this.state = {
active: false,
value: ""
};
}
selectItem(color) {
this.setState({ value: color, active: false });
}
setActive(state) {
this.setState({ active: state });
this.refs.dropdown.focus();
}
render() {
const { colors, styles, inputName } = this.props;
const pickerClasses = classNames('colorpicker-dropdown', { 'active': this.state.active });
const colorFields = colors.map((color, index) => {
const colorClasses = classNames('colorpicker-item', [`colorpicker-item-${color}`]);
return (
<div onClick={() => { this.selectItem(color) }} key={index} className="colorpicker-item-container">
<div className={colorClasses}></div>
</div>
);
});
return (
<div className="colorpicker">
<input type="text" className={styles} name={inputName} ref="component" value={this.state.value} onFocus={() => { this.setActive(true) }} />
<div onBlur={() => this.setActive(false) } onFocus={() => console.log('focus')} tabIndex="1" ref="dropdown" className={pickerClasses}>
{colorFields}
</div>
</div>
);
}
}
Upvotes: 31
Views: 137037
Reputation: 6922
All you need to do is get a reference to the element you want to programmatically set the focus on, and remember to set a tabIndex on it if it's by default unfocusable.
Example using function components:
import React, {useRef} from 'react';
const MyFC = () => {
const divRef = useRef<HTMLDivElement>(null);
return (
<>
<div ref={divRef} tabIndex={-1}>
I get focus when button is clicked
</div>
<button onClick={() => divRef.current?.focus()}>Focus</button>
</>
);
};
export default MyFC;
Upvotes: 3
Reputation: 3029
If somehow we don't have access to ref (Maybe using some third-party library or having our own custom component) then in order to do so in react we can make use of vanilla JS like so
;(document.getElementsByClassName('sort-dropdown-span-button')[0] as HTMLDivElement).focus()
Note: But that particular div must have class say sort-dropdown-span-button (like in above example) and tabIndex=0
Upvotes: 0
Reputation: 23
A little late to answer but the reason why your event handler is not working is probably because you are not binding your functions and so 'this' used inside the function would be undefined when you pass it as eg: "this.selectItem(color)"
In the constructor do:
this.selectItem = this.selectItem.bind(this)
this.setActive = this.setActive.bind(this)
Upvotes: 0
Reputation: 1014
This worked in my case
render: function(){
if(this.props.edit){
setTimeout(()=>{ this.divElement.focus() },0)
}
return <div ref={ divElement => this.divElement = divElement}
contentEditable={props.edit}/>
}
Upvotes: -2
Reputation: 886
React redraws the component every time you set the state, meaning that the component loses focus. In this kind of instances it is convenient to use the componentDidUpdate
or componentDidMount
methods if you want to focus the element based on a prop, or state element.
Keep in mind that as per React Lifecycle documentation, componentDidMount
will only happen after rendering the component for the first time on the screen, and in this call componentDidUpdate
will not occur, then for each new setState
, forceUpdate
call or the component receiving new props the componentDidUpdate
call will occur.
componentDidMount() {
this.focusDiv();
},
componentDidUpdate() {
if(this.state.active)
this.focusDiv();
},
focusDiv() {
ReactDOM.findDOMNode(this.refs.theDiv).focus();
}
Here is a JS fiddle you can play around with.
Upvotes: 31
Reputation: 36511
This is the problem:
this.setState({ active: state });
this.refs.component.focus();
Set state is rerendering your component and the call is asynchronous, so you are focusing, it's just immediately rerendering after it focuses and you lose focus. Try using the setState
callback
this.setState({ active: state }, () => {
this.refs.component.focus();
});
Upvotes: 9