I try to add focus on the input field when the element is mounted.
I use this code. When I press button on Header the search bar shows up, I add to it class open because
want my search to move with a help of transition. Search bar starts moving and get to its place and
the focus is applied. it's fine. Then I click "close" button to hide the search bar and it smoothly
return to its place(backwards, to become hidden). It's all right till now. Because after that, the search bar shows up
again and doesn't hide even though I pressed the close button! I expect that
onClick={() => { props.setVisibleSearchBar(false) }}
will hide my search. By the way, the style for "open" also doesn't applied when the search appears unexpectevely after the close btn is clicked(though the search is visible).
Header.jsx
const Header = () => {
const [visibleSearchBar, setVisibleSearchBar] = useState(false);
return (
<button onClick={() => setVisibleSearchBar(true)}>Show search bar</button>
<Search visibleSearchBar={visibleSearchBar}
setVisibleSearchBar={setVisibleSearchBar} />
);
}
Search.jsx
const Header = (props) => {
const [disabled, setDisabled] = useState(true);
let slideRef = useRef('');
let inputRef = useRef('');
useEffect(() => {
const callback = () => {
setDisabled(false);
inputRef.current.focus();
}
slideRef.current.addEventListener('transitionend', callback);
return () => slideRef.current.removeEventListener('transitionend', callback)
}, []);
return (
<div
className={classNames('header-inner__main-search-slide', { open: props.visibleSearchBar })}
ref={slideRef}>
<input ref={inputRef}
disabled={disabled}
className='header-inner__main-search-slide-field' />
<button
onClick={() => { props.setVisibleSearchBar(false) }}
className='header-inner__main-search-slide-close'> CLOSE
</button>
</div >
)
Played with your sanbox, here it is working fine - https://codesandbox.io/s/ecstatic-buck-d2rgx
So you problem was here:
const callback = () => {
setDisabled(false);
inputRef.current.focus();
}
You are setting a focus, whenever some transition finishes. But it is incorrect, you have to focus your input only when "open" transition finishes. It is important, because browser automatically scrolls to the element in focus, that's what was happening in this case, you was hiding input, but then focusing it, so browser "scrolled" it back.
Here is a fixed version of it:
if (slideRef.current.classList.contains("open")) {
inputRef.current.focus();
}
Why am i not using props
here - because, your useEffect
will be executed only on first render and if i would use props
here, i would use very first props passed to the component (because of closure). If you don't like to have to check classList
, other option would be to use state here (move 'open' flag to state)