diff --git a/electrum/gui/qt/invoice_list.py b/electrum/gui/qt/invoice_list.py
index 1b5773e06..c788627ef 100644
--- a/electrum/gui/qt/invoice_list.py
+++ b/electrum/gui/qt/invoice_list.py
@@ -48,6 +48,7 @@ ROLE_SORT_ORDER = Qt.UserRole + 2
 
 
 class InvoiceList(MyTreeView):
+    key_role = ROLE_REQUEST_ID
 
     class Columns(IntEnum):
         DATE = 0
@@ -74,14 +75,11 @@ class InvoiceList(MyTreeView):
         self.setSelectionMode(QAbstractItemView.ExtendedSelection)
         self.update()
 
-    def update_item(self, key, invoice: Invoice):
-        model = self.std_model
-        for row in range(0, model.rowCount()):
-            item = model.item(row, 0)
-            if item.data(ROLE_REQUEST_ID) == key:
-                break
-        else:
+    def refresh_row(self, key, row):
+        invoice = self.parent.wallet.invoices.get(key)
+        if invoice is None:
             return
+        model = self.std_model
         status_item = model.item(row, self.Columns.STATUS)
         status = self.parent.wallet.get_invoice_status(invoice)
         status_str = invoice.get_status_str(status)
@@ -125,11 +123,12 @@ class InvoiceList(MyTreeView):
         self.proxy.setDynamicSortFilter(True)
         # sort requests by date
         self.sortByColumn(self.Columns.DATE, Qt.DescendingOrder)
-        # hide list if empty
-        if self.parent.isVisible():
-            b = self.std_model.rowCount() > 0
-            self.setVisible(b)
-            self.parent.invoices_label.setVisible(b)
+        self.hide_if_empty()
+
+    def hide_if_empty(self):
+        b = self.std_model.rowCount() > 0
+        self.setVisible(b)
+        self.parent.invoices_label.setVisible(b)
 
     def create_menu(self, position):
         wallet = self.parent.wallet
diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py
index ab1dcc661..e4a80a034 100644
--- a/electrum/gui/qt/main_window.py
+++ b/electrum/gui/qt/main_window.py
@@ -875,7 +875,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
                 self.tray.showMessage("Electrum", message, QSystemTrayIcon.Information, 20000)
 
     def timer_actions(self):
-        self.request_list.refresh_status()
+        self.request_list.refresh_all()
+        self.invoice_list.refresh_all()
         # Note this runs in the GUI thread
         if self.need_update.is_set():
             self.need_update.clear()
@@ -1028,11 +1029,11 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
         if wallet != self.wallet:
             return
         self.history_model.refresh('update_tabs')
-        self.request_list.update()
+        self.request_list.refresh_all()
+        self.invoice_list.refresh_all()
         self.address_list.update()
         self.utxo_list.update()
         self.contact_list.update()
-        self.invoice_list.update()
         self.channels_list.update_rows.emit(wallet)
         self.update_completions()
 
@@ -1211,7 +1212,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
     def delete_requests(self, keys):
         for key in keys:
             self.wallet.delete_request(key)
-        self.request_list.update()
+            self.request_list.delete_item(key)
         self.clear_receive_tab()
 
     def delete_lightning_payreq(self, payreq_key):
@@ -1596,7 +1597,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
             self.notify(_('Payment received') + '\n' + key)
             self.need_update.set()
         else:
-            self.request_list.update_item(key, req)
+            self.request_list.refresh_item(key)
 
     def on_invoice_status(self, wallet, key):
         if wallet != self.wallet:
@@ -1606,9 +1607,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
             return
         status = self.wallet.get_invoice_status(invoice)
         if status == PR_PAID:
-            self.invoice_list.update()
+            self.invoice_list.delete_item(key)
         else:
-            self.invoice_list.update_item(key, invoice)
+            self.invoice_list.refresh_item(key)
 
     def on_payment_succeeded(self, wallet, key):
         description = self.wallet.get_label(key)
@@ -1944,7 +1945,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
     def delete_invoices(self, keys):
         for key in keys:
             self.wallet.delete_invoice(key)
-        self.invoice_list.update()
+            self.invoice_list.delete_item(key)
 
     def payment_request_ok(self):
         pr = self.payment_request
diff --git a/electrum/gui/qt/request_list.py b/electrum/gui/qt/request_list.py
index f18622d4e..4b3f1be04 100644
--- a/electrum/gui/qt/request_list.py
+++ b/electrum/gui/qt/request_list.py
@@ -48,6 +48,7 @@ ROLE_SORT_ORDER = Qt.UserRole + 2
 
 
 class RequestList(MyTreeView):
+    key_role = ROLE_KEY
 
     class Columns(IntEnum):
         DATE = 0
@@ -111,32 +112,14 @@ class RequestList(MyTreeView):
         super().clearSelection()
         self.selectionModel().clearCurrentIndex()
 
-    def refresh_status(self):
-        m = self.std_model
-        for r in range(m.rowCount()):
-            idx = m.index(r, self.Columns.STATUS)
-            date_idx = idx.sibling(idx.row(), self.Columns.DATE)
-            date_item = m.itemFromIndex(date_idx)
-            status_item = m.itemFromIndex(idx)
-            key = date_item.data(ROLE_KEY)
-            req = self.wallet.get_request(key)
-            if req:
-                status = self.parent.wallet.get_request_status(key)
-                status_str = req.get_status_str(status)
-                status_item.setText(status_str)
-                status_item.setIcon(read_QIcon(pr_icons.get(status)))
-
-    def update_item(self, key, invoice: Invoice):
+    def refresh_row(self, key, row):
         model = self.std_model
-        for row in range(0, model.rowCount()):
-            item = model.item(row, 0)
-            if item.data(ROLE_KEY) == key:
-                break
-        else:
+        request = self.wallet.get_request(key)
+        if request is None:
             return
         status_item = model.item(row, self.Columns.STATUS)
         status = self.parent.wallet.get_request_status(key)
-        status_str = invoice.get_status_str(status)
+        status_str = request.get_status_str(status)
         status_item.setText(status_str)
         status_item.setIcon(read_QIcon(pr_icons.get(status)))
 
@@ -176,14 +159,15 @@ class RequestList(MyTreeView):
         self.proxy.setDynamicSortFilter(True)
         # sort requests by date
         self.sortByColumn(self.Columns.DATE, Qt.DescendingOrder)
-        # hide list if empty
-        if self.parent.isVisible():
-            b = self.std_model.rowCount() > 0
-            self.setVisible(b)
-            self.parent.receive_requests_label.setVisible(b)
-            if not b:
-                # list got hidden, so selected item should also be cleared:
-                self.item_changed(None)
+        self.hide_if_empty()
+
+    def hide_if_empty(self):
+        b = self.std_model.rowCount() > 0
+        self.setVisible(b)
+        self.parent.receive_requests_label.setVisible(b)
+        if not b:
+            # list got hidden, so selected item should also be cleared:
+            self.item_changed(None)
 
     def create_menu(self, position):
         items = self.selected_in_column(0)
diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py
index 2468dcb50..40a4c1af9 100644
--- a/electrum/gui/qt/util.py
+++ b/electrum/gui/qt/util.py
@@ -783,6 +783,26 @@ class MyTreeView(QTreeView):
         self._pending_update = defer
         return defer
 
+    def find_row_by_key(self, key):
+        for row in range(0, self.std_model.rowCount()):
+            item = self.std_model.item(row, 0)
+            if item.data(self.key_role) == key:
+                return row
+
+    def refresh_all(self):
+        for row in range(0, self.std_model.rowCount()):
+            item = self.std_model.item(row, 0)
+            key = item.data(self.key_role)
+            self.refresh_row(key, row)
+
+    def refresh_item(self, key):
+        row = self.find_row_by_key(key)
+        self.refresh_row(key, row)
+
+    def delete_item(self, key):
+        row = self.find_row_by_key(key)
+        self.std_model.takeRow(row)
+        self.hide_if_empty()
 
 class MySortModel(QSortFilterProxyModel):
     def __init__(self, parent, *, sort_role):