         clear-force-close! (fn []
                              (swap! state assoc :force-close? false))
 
+        update-thread-text! (fn [thread-id text] (put! thread-text-chan {:thread-id thread-id
+                                                                         :content text}))
         set-text! (fn [text]
-                    (dispatch! :new-message-text {:thread-id @thread-id
-                                                  :content (.slice text 0 5000)}))
+                    (let [text (.slice text 0 5000)]
+                      (swap! state assoc :text text)
+                      (update-thread-text! @thread-id text)))
 
         update-text! (fn [f]
-                       (dispatch! :new-message-text
-                                  {:thread-id @thread-id
-                                   :content (f @thread-text)}))
+                       (swap! state update :text f)
+                       (update-thread-text! @thread-id (@state :text)))
 
         choose-result!
         (fn [result]

        kill-chan (chan)
        throttled-autocomplete-chan (debounce autocomplete-chan 100)

        thread-id (r/atom (config :thread-id))
        thread-text (subscribe [:thread-new-message] [thread-id])

        state (r/atom {:text thread-text
                       :force-close? false
                       :highlighted-result-index 0
                       :results nil})

                                     (resize-textbox (.. e -target)))})
                     :on-key-down (on-key-down
                                    {:on-submit (fn [e]
                                                  (send-message! config text)
                                                  (set-text! ""))})}])})))

(defn autocomplete-results-view [{:keys [results highlighted-result-index on-click]}]
