app\containers\SampleFirebaseApps\Todo\services\todoApi.js
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'],
}),
refetchTodos: builder.mutation({
queryFn: async () => ({
data: null
}),
invalidatesTags: ['Todo'],
}),
app\containers\SampleFirebaseApps\Todo\reducers\todoSlice.js
fetchTasksAction: (state, action) => {
const items = action.payload;
state.list = items;
},
app/containers/SampleFirebaseApps/Todo/index.js
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 })}
/>
)
app/components/TodoList/TaskList.js
const taskItems = tasks.map((task, index) => (
<TaskItem
removeTask={removeTask}
key={index.toString()}
task={task}
updateTask={updateTask}
/>
));
app\containers\SampleFirebaseApps\Todo\services\todoApi.js
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'],
}),
app/containers/SampleFirebaseApps/Todo/index.js
import { useCreateTodoMutation } from './services/todoApi';
const [createTodo] = useCreateTodoMutation();
<TaskForm handleSubmit={(payload) => createTodo(payload)} />
\app\components\TodoList\TaskForm.js
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>
)
app\containers\SampleFirebaseApps\Todo\services\todoApi.js
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'],
}),
app/containers/SampleFirebaseApps/Todo/index.js
import { useUpdateTodoMutation } from './services/todoApi';
const [updateTodo] = useUpdateTodoMutation();
return (
<TaskList
loading={isLoading}
removeTask={(payload) => deleteTodo(payload)}
tasks={filteredTasks()}
updateTask={(task, change) => updateTodo({ task, change })}
/>
)
app\components\TodoList\TaskItem.js
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"
/>
)
app\containers\SampleFirebaseApps\Todo\services\todoApi.js
deleteTodo: builder.mutation({
queryFn: async (task) => {
const todoId = task.id;
remove(ref(db, 'tasks/' + todoId));
return { data: { todoRemoved: true } };
},
invalidatesTags: ['Todo'],
})
app/containers/SampleFirebaseApps/Todo/index.js
import { useDeleteTodoMutation } from './services/todoApi';
const [deleteTodo] = useDeleteTodoMutation();
return (
<TaskList
loading={isLoading}
removeTask={(payload) => deleteTodo(payload)}
tasks={filteredTasks()}
updateTask={(task, change) => updateTodo({ task, change })}
/>
)
app\components\TodoList\TaskItem.js
const remove = () => {
removeTask(task);
setAnchorEl(null);
};
return (
<IconButton
className={
classNames(
classes.button,
editing && classes.hide
)
}
size="small"
onClick={remove}
>
<DeleteIcon />
</IconButton>
)