Read / Fetch



API Redux Toolkit Query (RTK)

  • File: app\containers\SampleFirebaseApps\Todo\services\todoApi.js
  • Call fetch action in API function
                              
    fetchTodos: builder.query({
      queryFn: async () => {
        const todoRef = child(dbRef, 'tasks/');
        const querySnapshot = await get(todoRef).then((snapshot) => {
          if (snapshot.exists()) {
            return snapshot.val();
          }
          return false;
        }).catch((error) => error);
    
        const todos = Object.keys(querySnapshot).map(key => ({
          id: key,
          ...querySnapshot[key]
        }));
        return { data: todos.reverse() };
      },
      providesTags: ['Todo'],
    }),
                              
                            
  • Refetch data changes
                              
    refetchTodos: builder.mutation({
      queryFn: async () => ({
        data: null
      }),
      invalidatesTags: ['Todo'],
    }),
                              
                            

Reducer/Slice

  • File: app\containers\SampleFirebaseApps\Todo\reducers\todoSlice.js
  • Set local state to load items in front-end side
                              
    fetchTasksAction: (state, action) => {
      const items = action.payload;
      state.list = items;
    },
                              
                            

Container

  • File: app/containers/SampleFirebaseApps/Todo/index.js
  • Load state data to container
                              
    import { fetchTasksAction } from './reducers/todoSlice';
    import { useFetchTodosQuery } from './services/todoApi';
    
    const taskList = useSelector(state => state.todoFb.list);
    const filteredTasks = () => {
      switch (filterType) {
        case 'active':
          return taskList.filter(task => !task.completed);
        case 'completed':
          return taskList.filter(task => task.completed);
        default:
          return taskList;
      }
    };
    
    const { data, isLoading } = useFetchTodosQuery();
    
    // Dispatcher
    const dispatch = useDispatch();
    
    useEffect(() => {
      dispatch(fetchTasksAction(data));
    }, [data]);
    
    
    return (
      <TaskList
        loading={isLoading}
        removeTask={(payload) => deleteTodo(payload)}
        tasks={filteredTasks()}
        updateTask={(task, change) => updateTodo({ task, change })}
      />
    )
                            

Components

  • File: app/components/TodoList/TaskList.js
  • Populate tasks prop data to component
                              
    const taskItems = tasks.map((task, index) => (
      <TaskItem
        removeTask={removeTask}
        key={index.toString()}
        task={task}
        updateTask={updateTask}
      />
    ));
                              
                            


Create



API Redux Toolkit Query (RTK)

  • File: app\containers\SampleFirebaseApps\Todo\services\todoApi.js
  • Call create task action in API function
                      
    createTodo: builder.mutation({
      queryFn: async (title) => {
        const todoId = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
        set(ref(db, 'tasks/' + todoId), {
          title,
          completed: false
        });
        return { data: { todoSubmited: true } };
      },
      invalidatesTags: ['Todo'],
    }),
                      
                    

Container

  • File: app/containers/SampleFirebaseApps/Todo/index.js
  • Dispatch create action in container
                      
    import { useCreateTodoMutation } from './services/todoApi';
    
    const [createTodo] = useCreateTodoMutation();
    
    <TaskForm handleSubmit={(payload) => createTodo(payload)} />
                      
                    

Component

  • File: \app\components\TodoList\TaskForm.js
  • Get and submit New task
                      
    const { intl, handleSubmit } = props;
    const handleSubmitForm = (event) => {
      event.preventDefault();
      const titleString = title.trim();
      if (titleString.length) handleSubmit(titleString);
      clearInput();
    };
    
    return (
      <form onSubmit={handleSubmitForm} noValidate>
         ...
      </form>
    )
                      
                    


Update



API Redux Toolkit Query (RTK)

  • File: app\containers\SampleFirebaseApps\Todo\services\todoApi.js
  • Call update task action API function
                      
    updateTodo: builder.mutation({
      queryFn: async (payload) => {
        const { task, change } = payload;
        const todoId = task.id;
        const updates = {};
    
        updates['/tasks/' + todoId] = { ...task, ...change };
        update(ref(db), updates);
    
        return { data: { todoChanged: true } };
      },
      invalidatesTags: ['Todo'],
    }),
                      
                    

Container

  • File: app/containers/SampleFirebaseApps/Todo/index.js
  • Dispatch update action in container
                      
    import { useUpdateTodoMutation } from './services/todoApi';
    
    const [updateTodo] = useUpdateTodoMutation();
    
    return (
      <TaskList
        loading={isLoading}
        removeTask={(payload) => deleteTodo(payload)}
        tasks={filteredTasks()}
        updateTask={(task, change) => updateTodo({ task, change })}
      />
    )
                      
                    

Component

  • File: app\components\TodoList\TaskItem.js
  • Get and send the updated value
                      
    const save = (event) => {
      if (editing) {
        const title = event.target.value.trim();
        if (title.length && title !== task.title) {
          updateTask(task, { title });
        }
        setEditing(false);
      }
    };
    
    const handleKeyUp = (event) => {
      if (event.keyCode === 13) {
        save(event);
      } else if (event.keyCode === 27) {
        setEditing(false);
      }
    };
    
    return (
      <input
        autoFocus // eslint-disable-line
        autoComplete="off"
        defaultValue={task.title}
        maxLength="64"
        onKeyUp={this.handleKeyUp}
        type="text"
      />
    )
      
      
                      
                    


Delete



API Redux Toolkit Query (RTK)

  • File: app\containers\SampleFirebaseApps\Todo\services\todoApi.js
  • Call remove task action in API function
                      
    deleteTodo: builder.mutation({
      queryFn: async (task) => {
        const todoId = task.id;
        remove(ref(db, 'tasks/' + todoId));
    
        return { data: { todoRemoved: true } };
      },
      invalidatesTags: ['Todo'],
    })
                      
                    

Container

  • File: app/containers/SampleFirebaseApps/Todo/index.js
  • Dispatch remove action in container
                    
    import { useDeleteTodoMutation } from './services/todoApi';
    
    const [deleteTodo] = useDeleteTodoMutation();
    
    return (
      <TaskList
        loading={isLoading}
        removeTask={(payload) => deleteTodo(payload)}
        tasks={filteredTasks()}
        updateTask={(task, change) => updateTodo({ task, change })}
      />
    )
                      
                    

Component

  • File: app\components\TodoList\TaskItem.js
  • Call remove function by onClick remove button
                      
    const remove = () => {
      removeTask(task);
      setAnchorEl(null);
    };
    
    return (
      <IconButton
        className={
          classNames(
            classes.button,
            editing && classes.hide
          )
        }
        size="small"
        onClick={remove}
      >
        <DeleteIcon />
      </IconButton>
    )