简体   繁体   中英

Strange React hooks behavior, can't access new state from a function

I use the library react-use-modal , and I'm trying to read the updated value of confirmLoading when inside the handleClick function.

handleClick does read the first value of confirmLoading defined when doing const [ confirmLoading, setConfirmLoading ] = useState(false) , but never updates when I setConfirmLoading inside handleOk .

I don't understand what I'm doing wrong

import { Button, Modal as ModalAntd } from 'antd'
import { useModal } from 'react-use-modal'

export interface ModalFormProps {
    form: React.ReactElement
}

export const ModalForm: React.FC = () => {
    const [ confirmLoading, setConfirmLoading ] = useState(false)
    const { showModal, closeModal } = useModal()

    const handleOk = () => {
        setConfirmLoading(true)
        setTimeout(() => {
            setConfirmLoading(false)
            closeModal()
        }, 1000)
    }

    const handleCancel = () => {
        closeModal()
    }

    const handleClick = () => {             
        showModal(({ show }) => (
            <ModalAntd                  
                onCancel={handleCancel}
                onOk={handleOk}
                title='Title'
                visible={show}
            >
                //  the value of confirmLoading is always the one defined 
                //  with useState at the beginning of the file.
                <p>{confirmLoading ? 'yes' : 'no'}</p>                  
            </ModalAntd>
        ))
    }

    return (
        <div>
            <Button onClick={handleClick}>
                Open Modal
            </Button>
        </div>
    )
}

This is happening because of closures. The component that you pass to showModal remembers confirmLoading and when you call function setConfirmLoading your component renders again and function handleClick is recreated. 'Old' handleClick and 'old' component in showModal know nothing about the new value in confirmLoading .

Try to do this:

export const ModalForm: React.FC = () => {
    const { showModal, closeModal } = useModal();

    const handleClick = () => {

        showModal(({ show }) => {
            const [ confirmLoading, setConfirmLoading ] = useState(false);
            const handleOk = () => {
                setConfirmLoading(true)
                setTimeout(() => {
                    setConfirmLoading(false)
                    closeModal()
                }, 1000)
            };

            const handleCancel = () => {
                closeModal()
            };

            return (
                <ModalAntd
                    onCancel={handleCancel}
                    onOk={handleOk}
                    title='Title'
                    visible={show}
                >
                    // the value of confirmLoading is always the one defined
                    // with useState at the beginning of the file.
                    <p>{confirmLoading ? 'yes' : 'no'}</p>
                </ModalAntd>
            );
        })
    };

    return (
        <div>
            <Button onClick={handleClick}>
                Open Modal
            </Button>
        </div>
    )
}


The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM