Remixing Usability

2022

with Performance

(he/him)

User Interface

User Experience

Usability

{...design}
{...design}

UI

UX

Usability

✨

Excuse me. That you?

click
mutation event
mutation request
response
update content
woohoo!

Don’t

go

chasing

waterfalls

💭 this song is from 1995

Mutations

Optimistic

Optimistic

let’s try something

click
mutation event
mutation request
response
update content
woohoo!
✅

“Expect...

...the unexpected”

those 1 every 999

click
mutation event
mutation request
💥
update content
woohoo!
update content
Pardon. retry?

important notes

if your App/API fails often, you probably have a bug

not a silver bullet

🐛

🔫

then

when?

when the response is not critical for the user experience

when you trust the availability of the resource

🐶

☀️

loader function

when a page loads

`GET`

requests

⬇️

⚙️

action function

when a data mutates

`POST`

requests

⬆️

⚙️

`PUT`
`DELETE`
`PATCH`
`useLoaderData()`
`useActionData()`

useTransition()

GET form submission
POST / PUT / PATCH / DELETE form submission

from remix

not react

⚠

navigation
idle
idle
loading
idle
idle
submitting
idle
idle
submitting
loading

1️⃣

2️⃣

3️⃣

const PageComponent = () => {
  const initialData = useLoaderData()
  const transition = useTransition()

  return (
    <h1>
      {transition.state === 'submitting'
        ? `Submitted ${transition.submission.formData.get('username')}`
        : `Already have ${initialData?.username || 'nothing'}`
       }
    </h1>
   )
 }

routes/page.jsx

demo

time

useFetcher()

This hook lets you plug your UI into your actions and loaders without navigating

-- from Remix docs

POST
PUT
DELETE
PATCH

Action

Function

Loader

Function

<Form>
<fetcher.Form>

vs

<form>

vs

HTML5 Logo

🪝

const PageComponent = () => {
  const { data, submission, state } = useFetcher()
  const initialData = useLoaderData()
  
  const formData = submission.formData

  const food = fetcher.data
    ? `${data.cuisine} ${data.dish}`
    : initialData.food

  return (
    <h1>
      {state === 'submitting'
        ? `We are eating ${formData.get('dish')} for dinner`
        : `We are eating ${food || 'nothing'} for dinner`
      }
    </h1>
 }

routes/page.jsx

demo

time

So, are Optimistic Mutations a 

thing?

No.

Tanstack Query

featuring

getServerSideProps
QueryClient
initialData

Hydrate page with data

cache query
mutate

✅

❌

Re-Render page w/ new data

update cache

Re-Render page w/ old data

pull from cache
warn user
function App({ Component, pageProps }) {
  const [queryClient] = useState(
    () => new QueryClient()
  )

  return (
    <QueryClientProvider client={queryClient}>
      {/*... app stuff goes here */}
    </QueryClientProvider>
  )
 }

pages/_app.jsx

function Page({ pageData }) {
  const { data } = useQuery(
    ['data'],
    () => {
      return getData(user)
    },
    {
      initialData: pageData,
    }
  )

  return <Component />
}

pages/page.jsx

const getServerSideProps = async ({
  req,
  res
}) => {
  const user = await getUser()
 
  return {
    props: {
      pageData: await fetchData(user)
    },
  }
}

pages/page.jsx

const useAddTodo = (user) => {
  const queryClient = useQueryClient()

  return useMutation(
    (newTodo: TodoProps) => addTodo(newTodo, userEmail), {
      onMutate: async (newTodo) => {
        await queryClient.cancelQueries(['todos'])

        const previousTodos = queryClient.getQueryData(['todos'])

        queryClient.setQueryData(['todos'], (oldTodos => [
          newTodo,
          ...oldTodos,
        ])

        return { previousTodos }
      },
      onError: (err, _newTodo, context) => {
        queryClient.setQueryData(['todos'], context.previousTodos)
      },
      onSettled: () => {
        queryClient.invalidateQueries(['todos'])
      },
    })
  )
}

hooks/query.jsx

demo

time

state chart

thanks

being optimistic is cool

Remixing Usability with Performance

By Atila

Remixing Usability with Performance

Remix is a framework revitalises web development by putting progressive enhancement in the front seat. It creates solutions that approximates developers to the platform. It uses Developer Experience as means to enforce web best practices and with that brought the term Optimistic UI back to our daily lives. Let's have a look at what features the Remix offers out-of-the-box to get developers creating high-quality web apps easily and deploying them anywhere that can run JavaScript.

  • 86