0

I use setModalConfirmVisible(true) but the state modalConfirmVisible does not update immediately. So, Modal does not display.

How can I update this state immediately?

See happened When I click Remove button. The console will show only false from

console.log(modalConfirmVisible)

  useEffect(() => {
    (async () => {
      try {
        setFetchLoading(true)
        setTransactions(await fetchTransactions())
        setFetchLoading(false)
      } catch (err) {
        console.error(err)
      }
    })()
  }, [modalConfirmVisible])

  async function handleRemoveTransaction(id) {
    setRemoveLoading(true)
    setModalConfirmVisible(true)
    console.log(modalConfirmVisible)
    await handleConfirmRemoveTransaction(true, id)
  }


  return (
    {modalConfirmVisible && (
      <ModalConfirm
        onConfirmRemove={handleConfirmRemoveTransaction}
        onCancel={() => setModalConfirmVisible(false)}
        visible={true} 
      />
    )}
  )


// ModalConfirm.js
const ModalConfirm = ({ onConfirmRemove, visible }) => {
  return (
    <Modal
      visible={visible}
      title="Do you want to delete these items?"
      icon={<ExclamationCircleOutlined />}
      content="When clicked the OK button, this dialog will be closed after 1 second"
      onOk={() => onConfirmRemove(true)}
      onCancel={() => onConfirmRemove(false)}
    />
  )
}
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
fResult
  • 477
  • 1
  • 5
  • 17
  • 1
    Where `ModalConfirm` comes from? Please show the code from that component – Vencovsky Mar 03 '20 at 15:11
  • Are you trying to, within `handleRemoveTransaction`, open the modal **AND** await the modal's `onConfirmRemove` callback to be called? This won't work as the state update is asynchronous and updated value isn't available for *this* render cycle. In other words, your awaiting the modal callback is blocking the modal from opening. – Drew Reese Mar 03 '20 at 15:16
  • 1
    State updates are async. You can't see them directly after calling `setState`. You will only see them during the next render that a state update triggers. But this should not be a problem. – trixn Mar 03 '20 at 15:23
  • 1
    Does this answer your question? [useState set method not reflecting change immediately](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately) – Emile Bergeron Mar 03 '20 at 15:24

2 Answers2

1

You should try to split out the logic of opening your modal from handling the confirmation. This allows the state update to set modalConfirmVisible and then on the next render cycle the confirmModal can open.

// from component in screen cap click remove, just open the modal
function openRemoveConfirmation() {
  setRemoveLoading(true)
  setModalConfirmVisible(true)
}

// handle confirmation separately
function handleRemoveTransaction(id) {
  handleConfirmRemoveTransaction(true, id)
}

return (
  {modalConfirmVisible && (
    <ModalConfirm
      onConfirmRemove={handleConfirmRemoveTransaction}
      onCancel={() => setModalConfirmVisible(false)}
      visible={true} 
    />
  )}
)
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
0

Because you are using react-hooks, so you change any state immediately.

The right way is to check the value of modalConfirmVisible in the next cycle. And because you setState and the state is changed, the function will execute again:

const [modalConfirmVisible, setModalConfirmVisible] = useState(false);

async function handleRemoveTransaction(id) {
  setRemoveLoading(true)
  setModalConfirmVisible(true)
  await handleConfirmRemoveTransaction(true, id)
}
console.log(modalConfirmVisible)
Stupidism
  • 113
  • 1
  • 2
  • 7