upmostly / modali

A delightful modal dialog component for React, built from the ground up to support React Hooks.
212 stars 23 forks source link

Why useRef is used? #23

Closed yairEO closed 4 years ago

yairEO commented 5 years ago

I am looking at the source code of this awesome package and am stumped upon this line

const [isModalVisible, setIsModalVisible] = useState(false);
const [isShown, setIsShown] = useState(false);
const isModalVisibleRef = useRef(isModalVisible);  // ← why useRef?
isModalVisibleRef.current = isModalVisible;        // ← and this..?

function toggle() {
    timeoutHack = setTimeout(() => {
        setIsModalVisible(!isModalVisibleRef.current);
        clearTimeout(timeoutHack);
    }, 10);
    setIsShown(!isShown);
    setHasToggledBefore(true);
}

I am deeply interested into what was the decision behind this piece of code

Thanks!

yairEO commented 5 years ago

Doesn't the isModalVisible persist anyway, even when the useModali function is called from multiple places?

jcrowson commented 5 years ago

@yairEO Great question! This is to do with how the setTimeout function works. It's a closure, and therefore, any values defined inside of it won't update once the React component updates. If we were to use a state value inside of the setTimeout it wouldn't update to its current value.

I talk about this particular problem at the end of setTimeout in React Components Using Hooks. It's an interesting problem that can cause a lot of headaches! 🤕

yairEO commented 5 years ago

Thanks for the clarification, I was very surprised at a similar situation where my state variable has seemed to be cached, and now, armed with the knowledge I've learned here, I will know how to deal with such cases better.

React hooks can really make coding more complex since they aren't intuitive.

jcrowson commented 5 years ago

@yairEO Agreed! There isn't a huge amount of documentation on Hooks. They're also fairly new, so we're still exploring them.