                   (if (vector? component)
                     (let [[component-id entity-id] component]
                       [(concat-keywords component-id entity-id)
-                       (get-component-state state
-                                            component-id
-                                            entity-id)])
+                       (cached-get-component-state state
+                                                   component-id
+                                                   entity-id)])
                     [component
-                     (get-component-state state
-                                          component
-                                          entity-id)])))
-        select-component-ids))
+                     (cached-get-component-state state
+                                                 component
+                                                 entity-id)])))
+        select-components))
 
 (defn get-component-context
-  "Returns a hashmap of context for use with a component fn."
-  [state entity-id component]
+  "Returns a hashmap of context for use with a component fn.
+   Args:
+   - state: The game state
+   - entity-id: The unique ID of the entity
+   - component: A hashmap representing the component meta data
+   - cached-get-component-state: A function for getting component-state from the game state.
+     This allows the passing of a memoized function to cache results"
+  [state entity-id component cached-get-component-state]
   (let [{:keys [subscriptions select-components]} component]
     (cond-> {}
       subscriptions (assoc :inbox

                            ;; the selectors, this
                            ;; ensures messages are
                            ;; per entity
                            (doall (map #(vector % entity-id) subscriptions))))
      select-components (select-component-states state entity-id select-components))))

(defn system-next-state [state component-id]
  (let [entity-ids (entities-with-component state component-id)
        component-states (get-all-component-state state component-id)
        component (get-component state component-id)
        component-fn (:fn component)
        event-accum (transient [])]
    [(assoc-in
      state

               (let [component-state (get component-states entity-id)
                     context (get-component-context state
                                                    entity-id
                                                    component
                                                    cached-get-component-state)
                     next-comp-state (component-fn entity-id
                                                   component-state
                                                   context)]
