I'm having a difficult time autofocusing an input field with semantic-ui-react. The documentation doesn't seem to include an autoFocus
prop and the focus
prop doesn't place the cursor inside the input field as would be expected.
<Form onSubmit={this.handleFormSubmit}>
<Form.Field>
<Form.Input
onChange={e => this.setState({ username: e.target.value })}
placeholder='Enter your username'
fluid />
</Form.Field>
</Form>
EDIT: This code works:
<Form onSubmit={this.handleFormSubmit}>
<Form.Input
onChange={e => this.setState({ username: e.target.value })}
placeholder="Enter your username"
autoFocus
fluid />
</Form>
There are a few ways to autofocus a React input field. You can use the autoFocus prop. This will work, but there is a caveat that we will get to. In this case, remember to use autoFocus, not autofocus. If you use autofocus instead, React will never actually set the autofocus DOM attribute.
But it doesn’t always work. If you add React to an existing application and render a component into a detached element, React will call focus() before the browser is ready, and the input will not be focused when it gets added to the DOM. So, instead of depending on React to call focus() on the input, we are going to do it ourselves.
The autofocus attribute is honored in ReactJS but only when the <input> element is re-rendered with React: autofocus is easy to use but only works when the <input> is initially rendered; since React intelligently only re-renders elements that have changed, the autofocus attribute isn't reliable in all cases.
To autofocus the first input element in the form after render, we use useEffect () hook and call the focus () method inside the hook. The dependency array should be an empty array to prevent multiple calls of focus () method on re-render.
The focus
prop is purely to add a focus effect on the input's appareance, it does not actually set the focus.
Any props unused by Semantic are passed down to the DOM element, so if you set an autoFocus
prop, it should go down to the input.
However, as explained in the Form
documentation:
Form.Input
Sugar for
<Form.Field control={Input} />
.
So your code should rather be:
const yourForm = (
<Form onSubmit={this.handleFormSubmit}>
<Form.Input
onChange={e => this.setState({ username: e.target.value })}
onSelect={() => this.setState({ usernameErr: false })}
placeholder="Enter your username"
error={usernameErr}
iconPosition="left"
name="username"
size="large"
icon="user"
fluid
autoFocus
/>
</Form>
)
Note that this only works if you want the focus to happen right when the wrapper component is mounted. If you want to focus the input after it has been mounted, you have to use a ref and call the focus()
method on it, just as showed in the documentation, like so:
class InputExampleRefFocus extends Component {
handleRef = (c) => {
this.inputRef = c
}
focus = () => {
this.inputRef.focus()
}
render() {
return (
<div>
<Button content='focus' onClick={this.focus} />
<Input ref={this.handleRef} placeholder='Search...' />
</div>
)
}
}
Hope that helps!
In order to tell the input field to focus, you need to create a reference (ref) to the input field as follows:
import React, { useState, useRef } from 'react';
import { Input, Button } from 'semantic-ui-react';
const SearchInputExample = () => {
const [searchValue, setSearchValue] = useState('');
// Create reference to the input field
const searchRef = useRef(null);
const handleSearchValueChange = event => setSearchValue(event.target.value);
return (
<div>
<Input
placeholder="Search..."
// Assign the ref created to a ref attribute
ref={searchRef}
value={searchValue}
onChange={handleSearchValueChange}
/>
<Button
onClick={() => {
setSearchValue('');
// Use the ref assigned to put the focus inside the input
searchRef.current.focus();
}}
>
Clear search (and focus)
</Button>
</div>
);
};
export default SearchInputExample;
You can read more about the useRef()
hook here
I would have assumed that semantic UI would pass all unknown props to the root element, the input. So if it does, you should be able to add the autoFocus attribute to it, if not, you will have to control which input is being focused in your state.
<Input placeholder='Search...' focus={this.state.focusedElement === "search"}/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With