Firestoreにデータが書き込めない、取得できない。
解決したいこと
ここに解決したい内容を記載してください。
リマインダーアプリを制作してます。
フロントエンドをReact、バックエンドをFirebase
Firestoreで実装中です。
発生している問題・エラー
フォームを作成してinputタグにクリックハンドラを
仕込んでuseReducerでdispatchしてます。Firestore用
にもう一つ関数を用意して、そちらでFirestoreに同じ
タスクを書き込んで取得したいのですが
関数が機能しません。console.log()が出力されません。
何が問題なのでしょうか?
ご教授お願いします。
出ているエラーメッセージを入力
エラーは出ていません。
または、問題・エラーが起きている画像をここにドラッグアンドドロップ
該当するソースコード
言語名
ソースコードを入力
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Firestoreのセキュリティルール(開発中のみ)
// rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// 全てのドキュメントへの読み書きを許可する
match /{document=**} {
allow read, write: if true;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Formコンポーネント
import React, { useEffect } from "react";
import { useState } from "react";
import { useDispatchTodos , useTodos , FirestoreContext } from "../context/TodoContext";
import { collection, setDoc, addDoc, doc, deleteDoc, updateDoc, getDocs, onSnapshot } from 'firebase/firestore';
import { db, app, firestore} from "../firebase";
import { getFirestore } from 'firebase/firestore';
import firebase from "firebase/app"; // firebaseモジュールをインポート
const Form = () => {
const dispatch = useDispatchTodos();
const { todos, AddTodos, fetchTodos,
enteredTodo, setEnteredTodo,
fireTodo, setFireTodo
} = useTodos();
const addTodo = () => {
const newTodo = {
id: Math.floor(Math.random() * 1e5),
content: fireTodo,
};
dispatch({ type: "todo/add", todo: newTodo, editing: false });
setFireTodo("");
AddTodos();
}
const allComplete = () => {
const neoTodo = {
completed: true
};
dispatch({type: "todo/reset", todo: neoTodo, editing: false });
}
// useEffect(() => {
// fetchTodos(firestore, dispatch);
// })
// const addTask = () => {
// const neoTodo7 = {
// id: Math.floor(Math.random() * 1e5),
// content: enteredTodo,
// };
// dispatch({type: "SET_TODOS", todo: neoTodo7, editing: false});
// setEnteredTodo("");
// }
return(
<div>
<input type="text" value={fireTodo} id="task" name="task"
onChange={(e) => setFireTodo(e.target.value)}/>
<div className="flex-box">
<button className="add" onClick={() => addTodo()}>
<div className="plus">
<span className="gif1"></span>
<span className="gif2"></span>
</div>
</button>
<button className="reset2" onClick={() => allComplete()}>
<div className="reset">
<img src="/icon_007476_32.png" alt="reset"></img>
</div>
</button>
</div>
</div>
);
}
export default Form;
//TodoContext
import React, { useMemo } from "react";
import { createContext, useContext, useReducer, useState, useEffect } from "react";
import { db, app, firestore} from "../firebase";
import { initializeApp } from "firebase/app";
import { getFirestore } from 'firebase/firestore';
import { getDatabase , ref, get, onValue } from "firebase/database";
import { collection, setDoc, addDoc, doc, deleteDoc, updateDoc, getDoc, onSnapshot } from 'firebase/firestore';
import firebase from "firebase/app"; // firebaseモジュールをインポート
import firebaseConfig from "../firebase";
// import 'firebase/firestore'; // Firestoreをインポート
// import 'firebase/database'; // Realtime Databaseをインポー
const TodoContext = createContext();
const TodoDispatchContext = createContext();
const todoReducer = (todos, action) => {
switch (action.type) {
case 'todo/add':
return [...todos, action.todo];
case 'todo/delete':
return todos.filter(todo => todo.id !== action.todo.id);
case 'todo/update':
return todos.map(_todo =>
_todo.id === action.todo.id ? { ..._todo, ...action.todo } : { ..._todo }
);
case 'todo/complete':
return todos.map(todo =>
todo.id === action.todo.id ? { ...todo, ...action.todo } : { ...todo }
);
case 'todo/reset':
return todos.filter(todo => null); // ここは正しくないので修正が必要
case 'todo/reserve':
return todos.map(_todo =>
_todo.id === action.todo.id
? { ..._todo, editingLock: true }
: { ..._todo, editingLock: false }
);
case 'todo/reserveColor':
return todos.map(_todo =>
_todo.editingDateTime
? { ..._todo, editingColor: true }
: { ..._todo, editingColor: false }
);
case 'todo/editingDateTime':
return todos.map(_todo =>
_todo.editingLock
? { ..._todo, editingDateTime: true }
: { ..._todo, editingDateTime: false }
);
case 'SET_TODOS':
return action.payload;
default:
return todos;
}
};
const TodoProvider = ({ children }) => {
const todoList = useMemo(() => [
{
id: 1,
content: "Make a restaurant reservation",
editing: false,
completed: false,
reserve: false,
editingLock: false,
editingColor: false,
editingDateTime: false
},
{
id: 2,
content: "send a letter",
editing: false,
completed: false,
reserve: false,
editingLock: false,
editingColor: false,
editingDateTime: false
},
{
id: 3,
content: "buy flowers",
editing: false,
completed: false,
reserve: false,
editingLock: false,
editingColor: false,
editingDateTime: false
},
], []);
const [ todos, dispatch ] = useReducer(todoReducer, todoList);
const [modalOpen, setModalOpen ] = useState(false);
const [selectedDate, setSelectedDate] = useState(new Date());
const [isDateSet, setIsDateSet] = useState(false);
const [isDateChecked, setIsDateChecked] = useState(false);
const [isTimeChecked, setIsTimeChecked] = useState(false);
const [isContainerDateCheck, setContainerDateCheck] = useState(false);
const [isContainerTimeCheck, setContainerTimeCheck] = useState(false);
const [selectedTime, setSelectedTime] = useState("12:00");
const [isTimeSet, setIsTimeSet] = useState(false);
const [displayTimePicker, setDisplayTimePicker] = useState(false);
const [displayDatePicker, setDisplayDatePicker] = useState(false);
const [loading, setLoading] = useState(true);
const [enteredTodo, setEnteredTodo] = useState("");
const [fireTodo, setFireTodo] = useState("");
const firebaseApp = initializeApp(firebaseConfig);
const firestore = getFirestore(firebaseApp);
const newTask = useMemo(() => ({
title: "newTask",
description: "todoリストの保存",
type: "string",
content: "ユーザーが入力したタスク",
editing: false,
completed: false,
reserve: false,
editingLock: false,
editingColor: false,
editingDateTime: "12:00"
}), []
//この関数が上手く機能しません ☟
useEffect(() => {
const fetchData = async () => {
const todoCollectionRef = collection(firestore, 'todoList');
try {
await addDoc(todoCollectionRef, newTask);
const docRef = doc(firestore, 'content')
const snapshot = await getDoc(docRef);
if(snapshot.exists()) {
console.log(snapshot.data()) // <- 修正
}
const todosData = [snapshot.data()]; // <- 修正
dispatch({ type: 'todo/add', payload: todosData });
console.log('Todos added to Firestore Successfully');
const unsubscribe = onSnapshot(todoCollectionRef, (snapshot) => {
const todosData = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
dispatch({ type: 'SET_TODOS', payload: todosData });
console.log('Todos updated in Firestore');
});
return () => unsubscribe();
} catch (error) {
console.error('Error adding todoList to Firestore:', error);
}
};
fetchData();
}, [firestore, newTask, todoList]);
//Todo追加
const AddTodos = () => {
try {
// マップされた todoList を Firestore に追加
(todoList.map(async todo => {
const todoCollection = collection(firestore, 'todoList');
const newTodoRef = addDoc(todoCollection, { content: todo.content, completed: false });
const dataTodo = { id: newTodoRef.id, content: todo.content, completed: false };
dispatch({ type: 'todo/add', todo: dataTodo, editing: false });
}));
console.log('Todos added to Firestore successfully');
} catch (error) {
console.error('Error adding todoList to Firestore:', error);
}
};
// Todo削除
const deleteTodo = async todoId => {
const todoDocRef = doc(firestore, 'todoList', todoId);
await deleteDoc(todoDocRef);
dispatch({ type: 'todo/delete', payload: todoId });
};
// Todo更新
const updateTodo = async (todoId, updatedFields) => {
const todoDocRef = doc(firestore, 'todoList', todoId);
await updateDoc(todoDocRef, updatedFields);
dispatch({ type: 'todo/update', payload: { id: todoId, updatedFields } });
};
// Todoリセット
const resetTodo = async (todoId, updatedFields) => {
const todoDocRef = doc(firestore, 'todoList', todoId);
await updateDoc(todoDocRef, updatedFields);
dispatch({ type: 'todo/reset', payload: { id: todoId, updatedFields } });
};
// タイマー予約
const reserveTodo = async (todoId, updatedFields) => {
const todoDocRef = doc(firestore, 'todoList', todoId);
await updateDoc(todoDocRef, updatedFields);
dispatch({ type: 'todo/reserve', payload: { id: todoId, updatedFields } });
};
// Todo予約色
const reserveColor = async (todoId, updatedFields) => {
const todoDocRef = doc(firestore, 'todoList', todoId);
await updateDoc(todoDocRef, updatedFields);
dispatch({ type: 'todo/reserveColor', payload: { id: todoId, updatedFields } });
};
// Todo日時編集
const editingDateTime = async (todoId, updatedFields) => {
const todoDocRef = doc(firestore, 'todoList', todoId);
await updateDoc(todoDocRef, updatedFields);
dispatch({ type: 'todo/editingDateTime', payload: { id: todoId, updatedFields } });
};
const handleDateChange = (date) => {
setSelectedDate(date);
setIsDateSet(true);
console.log(selectedDate)
}
const handleTimeChange = (event) => {
setSelectedTime(event.target.value);
setIsTimeSet(true)
console.log(selectedTime)
};
// console.log(selectedDate)
// console.log(selectedTime)
return (
<TodoContext.Provider value=
{{ todos, handleDateChange,
isDateChecked, setIsDateChecked, isTimeChecked , setIsTimeChecked,
isContainerTimeCheck, setContainerTimeCheck, isContainerDateCheck,
setContainerDateCheck, modalOpen, setModalOpen, selectedDate, setSelectedDate,
handleTimeChange, selectedTime, setSelectedTime,displayTimePicker, setDisplayTimePicker,
displayDatePicker, setDisplayDatePicker, isDateSet, setIsDateSet, isTimeSet, setIsTimeSet,
AddTodos, enteredTodo, setEnteredTodo, fireTodo, setFireTodo
}}>
<TodoDispatchContext.Provider value={dispatch}>
{children}
</TodoDispatchContext.Provider>
</TodoContext.Provider>
)
}
const useTodos = () => useContext(TodoContext);
const useDispatchTodos = () => useContext(TodoDispatchContext);
export { useTodos , useDispatchTodos , TodoProvider, getDoc };
自分で試したこと
ここに問題・エラーに対して試したことを記載してください。
FirebaseSDKの確認、Firebaseの初期化、Firestoreの初期化、それぞれのエクスポート、インポート
FireStoreのセキュリティルールの確認。
開発ツールでのデバッグ