Since you are already using hooks in your App, the only change you need to make is to use useRef
instead of createRef
to generate a ref to the list.
const Button = React.forwardRef((props, ref) => {
return (
<button
onClick={props.toggleList}
ref={ref}
>
button
</button>
);
})
const List = (props) => {
const list = React.useRef();
handleClick = (e) => {
const clickIsOutsideList = !list.current.contains(e.target);
console.log(list, clickIsOutsideList);
if (clickIsOutsideList) {
props.hideList();
}
}
React.useEffect(function addClickHandler() {
document.addEventListener('click', handleClick);
}, []);
return (
<ul ref={list}>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>
);
}
const App = () => {
const [ListHidden, setListHidden] = React.useState(true);
const button = React.useRef();
const toggleList = () => {
setListHidden(!ListHidden);
}
const hideList = () => {
setListHidden(true);
button.current.focus();
}
return (
<div className="App">
<Button
toggleList={toggleList}
ref={button}
/>
{
!ListHidden &&
<List hideList={hideList} />
}
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
Working demo
The reason that you need it is because on every render of your Functional component, a new ref will be generated if you make use of React.createRef
whereas useRef
is implemented such that it generates a ref when its called the first time and returns the same reference anytime in future re-renders.
P.S. A a thumb rule, you can say that useRef
should be used when you
want to have refs within functional components whereas createRef
should be used within class components.