re-frame

Ovi Stoica 2024-10-03T07:59:24.188549Z

What is the idiomatic way to handle data fetching in re-frame? I come from a react background and am searching for an equivalent to Redux Toolkit Query in re-frame. Redux data fetching:

export const api = createApi({
  reducerPath: 'api',
  tagTypes: [ApiTags.Activity],
  baseQuery: fetchBaseQuery({
    baseUrl: `${API_URL}api/v1`,
  }),
  endpoints: (builder) => ({
    getActivities: builder.query({
      query: () => `/activities`,
      providesTags: (_queryCache, _error, _params) => [
        { type: ApiTags.Activity, id: `LIST` },
      ],
    }),
  }),
})

export const {useGetActivitiesQuery} = api
As you can see here, we define an API endpoint, and this is now an API reducer. The API will create specific react hooks, which is a side-effect because when you call this hook, it will issue the request.
function MyComponent(){
    const {isLoading, data, isError, isSuccess} = useGetActivitiesQuery()
    if (isLoading) {return }
    if (isError) {return }
    return 
}
My initial reaction was to look for something similar in re-frame since redux and re-frame have similar ideas, although different in many parts. Redux does not differentiate between events and effects; it just has actions and thunk actions (async actions - usually with a side effect) But then I read https://ericnormand.me/article/react-vs-re-frame, and the first one is this exact pattern of fetching data on a lifecycle when a component mounts. • What is the idiomatic way to fetch data with re-frame? • Do you fetch all required data at the beginning or attach the effect to a navigation event?

Ovi Stoica 2024-10-14T06:34:18.243069Z

Thank you for the responses, guys! It seems like a kee-frame is what I was looking for.

kauppilainen 2024-10-04T10:39:41.496919Z

We used https://github.com/ingesolvoll/kee-frame to great success in the last project I was on. Particularly for the route-centric aspects.

👍 1
kauppilainen 2024-10-04T10:44:38.382489Z

Although we also utilised the success/failed pattern of requests with https://github.com/Day8/re-frame-http-fx

(rf/reg-event-fx ::submit-success
  (fn [{:keys [db]} [_ {:keys [path]} _response]]
    {:db (fork/set-submitting db path false)
     :dispatch [...]}))

(rf/reg-event-fx ::submit-failure
  (fn [{:keys [db]} [_ {:keys [path]} http-error]]
    {:db (fork/set-submitting db path false)
     ::ui/show-message {:message "Could not save your details"
                        :http-error http-error}}))

(rf/reg-event-fx ::submit
  (fn [{:keys [db]} [_ user-id {:keys [values path] :as fork-params}]]
    {:db (fork/set-submitting db path true)
     :http-xhrio (ui/build-http
                   {:method :put
                    :uri (str "/path/" user-id)
                    :params (attorney-common/transform-on-submit values)
                    :on-success [::submit-success fork-params]
                    :on-failure [::submit-failure fork-params]})}))

p-himik 2024-10-04T10:45:36.101249Z

Heh, even when I was still using re-frame-http-fx, I renamed :http-xhrio immediately. :)

😄 1
hkjels 2024-10-04T10:51:28.228309Z

Agreed! That one is not well named

hkjels 2024-10-03T09:19:48.480069Z

There's https://github.com/day8/re-frame-http-fx There's also a version that uses fetch if that's more your cup of tea

p-himik 2024-10-03T09:25:37.428909Z

I'd suggest using https://github.com/superstructor/re-frame-fetch-fx instead. > What is the idiomatic way to fetch data with re-frame? Create an event that uses an effect made by either of the two libraries (or create your own, it's trivial with js/fetch), create events that handle success and failure, use the initial event whenever you need to load some data. > Do you fetch all required data at the beginning or attach the effect to a navigation event? Depends on the app and use cases. In my apps, loading all the data that a user might need would keep them waiting for minutes to hours, so I load at navigation or some other explicit action, like expanding some panel.

ghaskins 2024-10-03T11:48:55.506939Z

You may already be familiar, but we also use https://github.com/ingesolvoll/kee-frame on top of re-frame for extra things like hooking route navigation to fx

👍 1
ghaskins 2024-10-03T11:52:15.155989Z

Then each route has constructs like

(k/reg-controller
 :alert
 {:params (fn [{{:keys [name]} :data {:keys [mrn]} :path-params :as e}]
            (when (= name :alert) mrn))
  :start  (fn [_ mrn]
            (let [logged-in @(rf/subscribe [::subs/logged-in])]
              (if logged-in
                [::init! mrn]
                [::login/login!])))
  :stop (fn [_ _]
          [::reset!])})

(rf/reg-event-fx
 ::init!
 (fn [{:keys [db]} [_ mrn]]
   (debug "init:" mrn)
   {:db (assoc-in db [::state :mrn] mrn)
    :fx [[:dispatch [::refresh!]]]}))

(rf/reg-event-fx
 ::refresh!
 (fn [{:keys [db]} _]
   ..
   {}))

ghaskins 2024-10-03T11:53:04.068759Z

and the “page load” logic goes in the refresh! fx

ghaskins 2024-10-03T11:54:24.554739Z

the nice thing is anything can trigger a refresh (websocket event, component action, etc)