question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support for optimistic updates

See original GitHub issue

I’m trying to figure out how to implement optimistic updates with createAsyncThunk and I came up with something like this:

export const updateTodo = createAsyncThunk<
  Todo,
  {
    id: Todo["id"];
    changes: Partial<Todo>;
  }
>("todos/update", async (args, { dispatch, getState, requestId }) => {
  const { id, changes } = args;

  const previousTodo = (getState().todos as TodosState).entities[id] as Todo;

  const begin = () => {
    const todo: Todo = {
      ...previousTodo,
      ...changes,
      updatedAt: new Date().toISOString()
    };

    dispatch(updateTodo.fulfilled(todo, requestId, args));
  };

  const commit = () => todosApi.update(id, changes);

  const rollback = () => {
    dispatch(updateTodo.fulfilled(previousTodo, requestId, args));
  };

  begin();

  try {
    return commit();
  } catch (error) {
    rollback();
    throw error;
  }
});

I’d like to share this piece of code because I believe that it could ba a good starting point for something like a generic helper for such actions.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:6
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

14reactions
arctouch-danielbastoscommented, May 18, 2020

Thanks for the suggestion! I believe RTK already supports optimistic updates. This is how you could implement the exact same feature without any changes to RTK:

type Todo = {
  id: number;
};

export const updateTodo = createAsyncThunk(
  'updateTodo',
  async (args: {
    todo: Todo;
    changes: Partial<Todo>;
    updatedAt: ReturnType<typeof Date.prototype.toISOString>;
  }) => {
    const { todo, changes } = args;
    todosApi.update(todo.id, changes);
  }
);

const slice = createSlice({
  name: 'todoList',
  // I'm ignoring createEntityAdapter here for simplicity
  initialState: { todos: {} as { [id: number]: Todo } },
  reducers: {},
  extraReducers: reducer =>
    reducer
      .addCase(updateTodo.pending, (state, action) => {
        const { todo, changes } = action.meta.arg;
        state.todos[todo.id] = {
          ...todo,
          ...changes,
        };
      })
      .addCase(updateTodo.rejected, (state, action) => {
        const { todo } = action.meta.arg;
        state.todos[todo.id] = todo;
      }),
});

This has a lot of benefits over the solution you proposed, including:

  1. Greater separation of concerns, since no component is responsible for both calling the API (aka dealing with side effects) and creating the Todo.
  2. In the same note, Thunks handle side-effects like API calls, while reducers handle business data logic.
  3. Code is more declarative. It’s easier to see that “when updateTodo is pending, we do this. When updateTodo is reject, we do that”.
1reaction
jordncommented, Dec 9, 2020

@AndrewCraswell are patches now exposed? I want to apply optimistic UI in the way you’ve suggested but I can see now documentation about it. @arctouch-danielbastos’s comment is very helpful but would lead to more duplicated code in my case

Read more comments on GitHub >

github_iconTop Results From Across the Web

Optimistic mutation results - Apollo GraphQL Docs
Optimistic mutation results · Update your UI before your server responds · The optimisticResponse option · Optimistic mutation lifecycle · Example: Adding a...
Read more >
Optimistic Updates - Query
Optimistic Updates. When you optimistically update your state before performing a mutation, there is a chance that the mutation will fail.
Read more >
Optimistic updates with concurrency control | by Alan Torres
Optimistic updates is a common pattern to improve the user experience by allowing the UI to behave as if a request to your...
Read more >
The Magic of Optimistic UI Updates with React and Redux
An optimistic UI update is an update in the user interface showing the final result even before the change requested to the server...
Read more >
what is `optimistic updates` in front-end development
In an optimistic update the UI behaves as though a change was successfully completed before receiving confirmation from the server that it ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found