Skip to content

Commit

Permalink
Dynamically Hide and Show Loading Spinner
Browse files Browse the repository at this point in the history
For comparison [see this commit][commit]

This commit is a slight divergence from Stimulus. Superglue does not have global
callbacks like `turbolinks:request-start`, if you need to do something before a
request starts, you must do so explicitly.

The behavior of showing a loading indicator requires an optimistic update. We
have to change the loading state to `true` before we make a request, and
change it to `false` when we're done with the request.

To make this feature work, add your customizations to the generated
`application_visit.js` and `pagesSlice`.

Superglue leans on Redux to give you the option of creating your own action
creators, and reducers. The Superglue installer already sets up a place where you
can put this logic.

For our purposes, we need to set the loading indicator on the current page to
`false`. Superglue's state shape is like Turbolink's internal state, a hash where the
urls are the keys and the values are the pages's content. We also recieve the
current key from the passed in props as `this.props.pageKey`.

Once we've created our action creator, we dispatch it with the `pageKey` to
toggle the current page's loading state, here's the meat of the functionality in
`pagesSlice`:

```
+  reducers: {
+    showLoading: (state, action) => {
+      const {pageKey} = action.payload;
+      const { seatingMap } = state[pageKey].data
+      seatingMap.loading = true
+    },
+    hideLoading: (state, action) => {
+      const {pageKey} = action.payload;
+      const { seatingMap } = state[pageKey].data
+      seatingMap.loading = false
+    }
+  }
```

[commit]: seanpdoyle@7169787
  • Loading branch information
jho406 committed Oct 8, 2023
1 parent 183663e commit 8917239
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 3 deletions.
8 changes: 6 additions & 2 deletions app/components/SeatingMap.js
Expand Up @@ -72,13 +72,17 @@ export default class extends React.Component {
}

render() {
const { sections } = this.props
const {
sections,
loading
} = this.props
const sectionElements = buildSectionElements(sections)
const loadingClass = loading && 'is-loading'

return(
<>
<div
className="syos-frame__map-overlay syos-loader-overlay is-loading"
className={`syos-frame__map-overlay syos-loader-overlay ${loadingClass}`}
aria-hidden="true"
>
<SVG src={ loadingSvg } className="syos-icon" title="zoom in"/>
Expand Down
7 changes: 6 additions & 1 deletion app/javascript/application_visit.js
@@ -1,4 +1,7 @@
import { visit, remote } from '@thoughtbot/superglue/action_creators'
import { pagesSlice } from './slices/pages'

const { showLoading, hideLoading } = pagesSlice.actions

export function buildVisitAndRemote(ref, store) {
const appRemote = (...args) => {
Expand All @@ -9,7 +12,8 @@ export function buildVisitAndRemote(ref, store) {
// Do something before
// e.g, show loading state, you can access the current pageKey
// via store.getState().superglue.currentPageKey
let { action } = args
const { currentPageKey } = store.getState().superglue
store.dispatch(showLoading({ pageKey: currentPageKey }))

return store
.dispatch(visit(...args))
Expand All @@ -32,6 +36,7 @@ export function buildVisitAndRemote(ref, store) {
// Do something after
// e.g, hide loading state, you can access the changed pageKey
// via getState().superglue.currentPageKey
store.dispatch(hideLoading({ pageKey: currentPageKey }))
})
.catch((err) => {
const response = err.response
Expand Down
12 changes: 12 additions & 0 deletions app/javascript/slices/pages.js
Expand Up @@ -3,6 +3,18 @@ import { saveResponse, beforeVisit } from '../actions'

export const pagesSlice = createSlice({
name: 'pages',
reducers: {
showLoading: (state, action) => {
const {pageKey} = action.payload;
const { seatingMap } = state[pageKey].data
seatingMap.loading = true
},
hideLoading: (state, action) => {
const {pageKey} = action.payload;
const { seatingMap } = state[pageKey].data
seatingMap.loading = false
}
}
// extraReducers: (builder) => {
// builder.addCase(beforeVisit, (state, action) => {
// const {currentPageKey} = action.payload
Expand Down
1 change: 1 addition & 0 deletions app/views/seats/_seating_map.json.props
@@ -1,4 +1,5 @@
json.floor floor.name
json.loading false

json.sections do
json.array! sections do |section|
Expand Down

0 comments on commit 8917239

Please sign in to comment.