cleanup: round 2; lifecycle methods
diff --git a/www/board/agenda/views/buttons/approve.js.rb b/www/board/agenda/views/buttons/approve.js.rb
index d1c1ae6..94e5fed 100644
--- a/www/board/agenda/views/buttons/approve.js.rb
+++ b/www/board/agenda/views/buttons/approve.js.rb
@@ -12,14 +12,9 @@
     _button.btn.btn_primary @request, onClick: self.click, disabled: @disabled
   end
 
-  # set request and button text on initial load
-  def componentWillMount()
-    self.componentWillReceiveProps()
-  end
-
   # set request (and button text) depending on whether or not the
   # not this items was previously approved
-  def componentWillReceiveProps()
+  def created()
     if Pending.approved.include? @@item.attach
       @request = 'unapprove'
     elsif Pending.unapproved.include? @@item.attach
diff --git a/www/board/agenda/views/buttons/attend.js.rb b/www/board/agenda/views/buttons/attend.js.rb
index 7d0dd9e..c7b10b4 100644
--- a/www/board/agenda/views/buttons/attend.js.rb
+++ b/www/board/agenda/views/buttons/attend.js.rb
@@ -11,12 +11,8 @@
       onClick: self.click, disabled: @disabled
   end
 
-  def componentWillMount()
-    self.componentWillReceiveProps()
-  end
-
   # match person by either userid or name
-  def componentWillReceiveProps()
+  def created()
     person = @@item.people[Server.userid]
     if person
       @attending = person.attending
diff --git a/www/board/agenda/views/buttons/draft-minutes.js.rb b/www/board/agenda/views/buttons/draft-minutes.js.rb
index 0181ef4..5121195 100644
--- a/www/board/agenda/views/buttons/draft-minutes.js.rb
+++ b/www/board/agenda/views/buttons/draft-minutes.js.rb
@@ -29,7 +29,7 @@
   end
 
   # autofocus on minute text; fetch draft
-  def componentDidMount()
+  def mounted()
     @draft = ''
     jQuery('#draft-minute-form').on 'shown.bs.modal' do
       retrieve "draft/#{Agenda.title.gsub('-', '_')}", :text do |draft|
diff --git a/www/board/agenda/views/buttons/message.js.rb b/www/board/agenda/views/buttons/message.js.rb
index 51a509d..e39ab8e 100644
--- a/www/board/agenda/views/buttons/message.js.rb
+++ b/www/board/agenda/views/buttons/message.js.rb
@@ -15,7 +15,7 @@
   end
 
   # autofocus on the chat message when the page is initially displayed
-  def componentDidMount()
+  def mounted()
     document.getElementById("chatMessage").focus()
   end
 
diff --git a/www/board/agenda/views/buttons/reminders.js.rb b/www/board/agenda/views/buttons/reminders.js.rb
index f0506c2..7298370 100644
--- a/www/board/agenda/views/buttons/reminders.js.rb
+++ b/www/board/agenda/views/buttons/reminders.js.rb
@@ -36,7 +36,7 @@
   end
 
   # wire up event handlers
-  def componentDidMount()
+  def mounted()
     Array(document.querySelectorAll('.btn-primary')).each do |button|
       if button.getAttribute('data-target') == '#reminder-form'
         button.onclick = self.loadText
diff --git a/www/board/agenda/views/buttons/showseen.js.rb b/www/board/agenda/views/buttons/showseen.js.rb
index 3f31724..664dac5 100644
--- a/www/board/agenda/views/buttons/showseen.js.rb
+++ b/www/board/agenda/views/buttons/showseen.js.rb
@@ -10,16 +10,20 @@
     _button.btn.btn_primary @label, onClick: self.click
   end
 
-  def componentWillReceiveProps()
+  def created()
+    self.changeLabel()
+  end
+
+  def click(event)
+    Main.view.toggleseen()
+    self.changeLabel()
+  end
+
+  def changeLabel()
     if Main.view and !Main.view.showseen()
       @label = 'hide seen'
     else
       @label = 'show seen'
     end
   end
-
-  def click(event)
-    Main.view.toggleseen()
-    self.componentWillReceiveProps()
-  end
 end
diff --git a/www/board/agenda/views/elements/pns.rb b/www/board/agenda/views/elements/pns.rb
index 7d910ee..b0f2449 100644
--- a/www/board/agenda/views/elements/pns.rb
+++ b/www/board/agenda/views/elements/pns.rb
@@ -20,7 +20,7 @@
   end
 
   # initial mount: fetch podlingnamesearch data unless already downloaded
-  def componentDidMount()
+  def mounted()
     if Server.podlingnamesearch
       self.check(self.props)
     else
@@ -31,11 +31,6 @@
     end
   end
 
-  # when properties (in particular: title) changes, lookup name again
-  def componentWillReceiveProps(newprops)
-    self.check(newprops)
-  end
-
   # lookup name in the establish resolution against the podlingnamesearches
   def check(props)
     @results = nil
diff --git a/www/board/agenda/views/pages/action-items.js.rb b/www/board/agenda/views/pages/action-items.js.rb
index 7c65132..a14d96c 100644
--- a/www/board/agenda/views/pages/action-items.js.rb
+++ b/www/board/agenda/views/pages/action-items.js.rb
@@ -176,7 +176,7 @@
   end
 
   # autofocus on action status in update action form
-  def componentDidMount()
+  def mounted()
     jQuery('#updateStatusForm').on 'shown.bs.modal' do
       ~statusText.focus()
     end
diff --git a/www/board/agenda/views/pages/adjournment.js.rb b/www/board/agenda/views/pages/adjournment.js.rb
index 653f192..74b027d 100644
--- a/www/board/agenda/views/pages/adjournment.js.rb
+++ b/www/board/agenda/views/pages/adjournment.js.rb
@@ -216,13 +216,8 @@
     @podlings = []
   end
 
-  # check for minutes being completed on first load
-  def componentDidMount()
-    self.componentWillReceiveProps()
-  end
-
   # update check marks based on current Todo list
-  def componentWillReceiveProps()
+  def created()
     @podlings = Todos.establish
 
     # uncheck podlings that were removed
diff --git a/www/board/agenda/views/pages/backchannel.js.rb b/www/board/agenda/views/pages/backchannel.js.rb
index c45af45..805c3f4 100644
--- a/www/board/agenda/views/pages/backchannel.js.rb
+++ b/www/board/agenda/views/pages/backchannel.js.rb
@@ -62,13 +62,13 @@
   end
 
   # on initial display, fetch backlog
-  def componentDidMount()
+  def mounted()
     Main.scrollTo = -1
     Chat.fetch_backlog()
   end
 
   # if we are at the bottom of the page, keep it that way
-  def componentWillUpdate()
+  def beforeUpdate()
     if 
       window.pageYOffset + window.innerHeight >=
       document.documentElement.scrollHeight
diff --git a/www/board/agenda/views/pages/cache.js.rb b/www/board/agenda/views/pages/cache.js.rb
index d3e6fff..928357b 100644
--- a/www/board/agenda/views/pages/cache.js.rb
+++ b/www/board/agenda/views/pages/cache.js.rb
@@ -66,13 +66,8 @@
 
   end
 
-  # update on first update
-  def componentDidMount()
-    self.componentWillReceiveProps()
-  end
-
   # update caches
-  def componentWillReceiveProps()
+  def created()
     if defined? caches
       caches.open('board/agenda').then do |cache|
         cache.matchAll().then do |responses|
@@ -102,13 +97,8 @@
       disabled: @disabled
   end 
 
-  # update on first update
-  def componentDidMount()
-    self.componentWillReceiveProps()
-  end
-
   # enable button if there is anything in the cache
-  def componentWillReceiveProps()
+  def created()
     if defined? caches
       caches.open('board/agenda').then do |cache|
         cache.matchAll().then do |responses|
@@ -189,7 +179,7 @@
   end
 
   # update on first update
-  def componentDidMount()
+  def mounted()
     if defined? caches
       basename = location.href.split('/').pop()
       basename = '' if basename == 'index.html'
diff --git a/www/board/agenda/views/pages/fy22.js.rb b/www/board/agenda/views/pages/fy22.js.rb
index 1ff5405..dab699e 100644
--- a/www/board/agenda/views/pages/fy22.js.rb
+++ b/www/board/agenda/views/pages/fy22.js.rb
@@ -327,7 +327,7 @@
   end
 
   # receive updated budget values
-  def componentWillReceiveProps()
+  def created()
     budget = Minutes.get('budget')
 
     if budget and budget != @budget and Minutes.started
diff --git a/www/board/agenda/views/pages/search.js.rb b/www/board/agenda/views/pages/search.js.rb
index 6669e11..aba2a82 100644
--- a/www/board/agenda/views/pages/search.js.rb
+++ b/www/board/agenda/views/pages/search.js.rb
@@ -57,12 +57,16 @@
   end
 
   # set history on initial rendering
-  def componentDidMount()
-    self.componentDidUpdate()
+  def mounted()
+    self.updateHistory()
   end
 
   # replace history state on subsequent renderings
-  def componentDidUpdate()
+  def updated()
+    self.updateHistory()
+  end
+
+  def updateHistory()
     state = {path: 'search', query: @text}
 
     if state.query
diff --git a/www/board/agenda/views/pages/select-actions.rb b/www/board/agenda/views/pages/select-actions.rb
index 6a93f4d..f1d524c 100644
--- a/www/board/agenda/views/pages/select-actions.rb
+++ b/www/board/agenda/views/pages/select-actions.rb
@@ -27,7 +27,7 @@
     end
   end
 
-  def componentDidMount()
+  def mounted()
     retrieve 'potential-actions', :json do |response|
       if response
         SelectActions.list = response.actions
diff --git a/www/board/agenda/views/pages/shepherd.js.rb b/www/board/agenda/views/pages/shepherd.js.rb
index 9e33b76..5cd5a26 100644
--- a/www/board/agenda/views/pages/shepherd.js.rb
+++ b/www/board/agenda/views/pages/shepherd.js.rb
@@ -70,7 +70,7 @@
   end
 
   # Fetch followup items
-  def componentDidMount()
+  def mounted()
     # if cached, reuse
     if Shepherd.followup
       @followup = Shepherd.followup