I tried to list the ids of the users under the users folder in the firebase firestore but it didn't work, can you help?
const [users, setUsers] = useState([]);
const getList = () => {
const subscriber = firestore()
.collection('users')
.doc()
.get()
.then(result => {
setUsers(result.data());
});
console.log(users)
return () => subscriber();
}
useEffect(() => {
setisLoading(true)
getList()
setisLoading(false)
}, []);
Related
const Notes = () => {
const history = useNavigate();
const [apiData, setApiData] = useState([]);
useEffect(() => {
axios
.get(`https://6390acc765ff4183111b53e9.mockapi.io/notes`)
.then((getData) => {
setApiData(getData.data);
});
}, []);
const onDelete = (id) => {
axios
.delete(`https://6390acc765ff4183111b53e9.mockapi.io/notes/${id}`)
.then(() => {
history("/notes");
});
};
This way I can delete the note that i fetched earlier, but it still appears on the screen until I refresh manually. It doesn't also go to /notes because i am already on /notes
You can either return the updated data in the delete response to update the local state, or you can trigger a refetch of the data after a successful deletion.
Refetch Example:
const Notes = () => {
const history = useNavigate();
const [apiData, setApiData] = useState([]);
const fetchNotes = useCallback(async () => {
const getData = await axios
.get(`https://6390acc765ff4183111b53e9.mockapi.io/notes`);
setApiData(getData.data);
}, []);
useEffect(() => {
fetchNotes();
}, [fetchNotes]);
const onDelete = async (id) => {
await axios
.delete(`https://6390acc765ff4183111b53e9.mockapi.io/notes/${id}`);
fetchNotes();
history("/notes");
};
...
Returned response Example*:
const Notes = () => {
const history = useNavigate();
const [apiData, setApiData] = useState([]);
useEffect(() => {
axios
.get(`https://6390acc765ff4183111b53e9.mockapi.io/notes`)
.then((getData) => {
setApiData(getData.data);
});
}, []);
const onDelete = async (id) => {
const getData = await axios
.delete(`https://6390acc765ff4183111b53e9.mockapi.io/notes/${id}`);
setApiData(getData.data);
history("/notes");
};
...
*Note: This requires updating the backend code to return the updated data in the response.
Hi i have this code i have using firebase v9 web. here is my code:
const [post, setPosts] = useState([]);
useEffect(() => {
const q = query(collection(db, "posts"));
onSnapshot(q, (querySnapshot) => {
setPosts(
querySnapshot.docs.map((doc) => ({ id: doc.id, data: doc.data() }))
);
});
});
The documentation has examples of both V8 name-spaced and V9 modular syntax:
import { getFirestore, collection, query, where, onSnapshot } from "firebase/firestore";
const db = getFirestore()
const q = query(collection(db, "posts"));
const unsubscribe = onSnapshot(q, (querySnapshot) => {
setPosts(querySnapshot.docs.map((doc) => ({ id: doc.id, data: doc.data() })))
});
I used to create the firebaseApp which I could use later on in the application. Since firebase#9 I got the same error. Now i create the firebaseApp before the database call which seems to work.
const [post, setPosts] = useState([]);
useEffect(() => {
const app = initializeApp(firebaseOption);
const db = getFirestore(app);
const q = query(collection(db, "posts"));
onSnapshot(q, (querySnapshot) => {
setPosts(
querySnapshot.docs.map((doc) => ({ id: doc.id, data: doc.data() }))
);
});
});
I'm creating lobby for game and I want to display player list. I'm watching for new players in room.
const [roomUsers, setRoomUsers] = useState([])
useEffect(() => {
if (room)
DB.collection("room_users").where("room_id", "==", room.id)
.onSnapshot((querySnapshot) => {
const newRoomUsers = [];
querySnapshot.forEach((doc) => {
newRoomUsers.push(doc.data());
});
setRoomUsers(newRoomUsers)
});
})
When I join in the second window, the number of players changes but the list updates over time. When I join more times, the list stops updating at all.
<h4>Players list ({roomUsers.length}/4)</h4>
{roomUsers.map(roomUser => (
<PlayerListItem
roomUser={roomUser}
owner={roomUser.uuid === room.owner}
/>
))}
In PlayerListItem component I am fetching the user via uuid
const [user, setUser] = useState(null)
useEffect(() => {
DB.collection('users').where('uuid', '==', roomUser.uuid).get().then(snapshot => {
if (!snapshot.empty)
setUser(snapshot.docs[0].data())
})
}, [])
Then I return the username through the component.
Sometimes the same username appears twice in the list instead of different
Your useEffect is missing the dependencies array. It should also return the cleanup function
useEffect(() => {
if (!room) {
return;
}
const unsub = DB.collection("room_users").where("room_id", "==", room.id)
.onSnapshot((querySnapshot) => {
const newRoomUsers = [];
querySnapshot.forEach((doc) => {
newRoomUsers.push(doc.data());
});
setRoomUsers((currVal) => {
console.log({currVal, newRoomUsers})
const newVal = [] // change this to be correct
return newVal
})
});
return () => unsub();
}, [room])
I am trying to let the FlatList get 20 posts from Firestore and render 20. when the end is reached I would like to call the getPosts method to get the next 20 posts which means I will have to have a way to save the last known cursor. This is what I was trying to do when converting class component to hooks.
Please can someone help me , no one answered my last question about this
const Posts = (props) => {
//How to get 20 posts from firebase and then render 20 more when the end is reached
const [allPosts, setAllPosts] = useState();
const [loading, setLoading] = useState(true)
const [isRefreshing, setRefreshing] = useState(false);
useEffect(() => {
getPosts();
}, []);
const getPosts = async () => {
try {
var all = [];
const unsubscribe = await firebase
.firestore()
.collection("Posts")
.orderBy("timestamp",'desc')
.get()
.then((querySnapshot) => {
querySnapshot.docs.forEach((doc) => {
all.push(doc.data());
});
setLoading(false);
});
setAllPosts(all);
if(currentUser === null){
unsubscribe()
}
} catch (err) {
setLoading(false);
}
};
const onRefresh = useCallback(() => {
setRefreshing(true);
getPosts()
.then(() => {
setRefreshing(false);
})
.catch((error) => {
setRefreshing(false); // false isRefreshing flag for disable pull to refresh
Alert.alert("An error occured", "Please try again later");
});
}, []);
return (
<FlatList
data={allRecipes}
refreshControl={
<RefreshControl
refreshing={isRefreshing}
onRefresh={onRefresh}
/>
}
initialNumToRender={20}
keyExtractor={(item, index) => item.postId}
renderItem={renderItem}
/>
);
}
const Posts = () =>{
const [posts, setPosts] = useState();
const [data, setData] = useState();
const addPosts = posts => {
setData({...data,...posts})
// `setData` is async , use posts directly
setPosts(Object.values(posts).sort((a, b) => a.timestamp < b.timestamp))
};
}
You need to add a scroll event listener here
something like:
const Posts = (props) => {
useEffect(() => {
window.addEventListener('scroll', () => {
if (window.scrollY >= (document.body.offsetHeight + window.innerHeight)) {
// fetch more posts here
}
});
});
// ...rest of the codes
}
I have no idea why is my function looping when I use useStates,
Can anyone figure out the problem.
It loops over and over,this is what appears in my console.log inside the snapshot
`function Classtab() {
const [userName, setuserName] = React.useState(null)
const [userType, setuserType] = React.useState(null)
const [userEmail, setuserEmail] = React.useState(null)
const [userCourse, setuserCourse] = React.useState([])
const [registeredCourse, setregisteredCourse] = React.useState([])
firebase.auth().onAuthStateChanged((user) => {
if(user){
var db = firebase.firestore()
db.collection('user').doc(user.uid)
.get()
.then(snapshot => {
setuserName( snapshot.data().name)
setuserType( snapshot.data().type)
setuserCourse( snapshot.data().course)
setuserEmail( user.email)
console.log(userCourse)
userCourse.map(course => {
db.doc(course).get().then(
snapshot => {setregisteredCourse([...registeredCourse, snapshot.data().name])}
)
}
)
}).catch(error => console.log(error))}else{}
})
return(...)`
You need to move your auth code into useEffect. What's happening right now is that you are running onAuthStateChanged on every render. And each time that returns, it causes another render, causing it to infinitely add more subscriptions.
I've modified your code to prevent the infinite re-renders and allow userCourse to be the correct value in the promise.then function. What it was originally would've had userCourse in the function to always be an empty array (due to the closure).
function Classtab() {
const [userName, setuserName] = React.useState(null);
const [userType, setuserType] = React.useState(null);
const [userEmail, setuserEmail] = React.useState(null);
const [userCourse, setuserCourse] = React.useState([]);
const [registeredCourse, setregisteredCourse] = React.useState([]);
const registeredCourseRef = useRef(registeredCourse);
useEffect(()=>{
registeredCourseRef.current = registeredCourse;
},[registeredCourse])
useEffect(() => {
const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
if (user) {
var db = firebase.firestore();
db.collection('user')
.doc(user.uid)
.get()
.then((snapshot) => {
setuserName(snapshot.data().name);
setuserType(snapshot.data().type);
const userCourse = snapshot.data().course;
setuserCourse(userCourse);
setuserEmail(user.email);
console.log(userCourse);
userCourse.map((course) => {
db.doc(course)
.get()
.then((snapshot) => {
setregisteredCourse((registeredCourse)=>[
...registeredCourse,
snapshot.data().name,
]);
});
});
})
.catch((error) => console.log(error));
} else {
}
});
return () => {
unsubscribe();
};
//Need to have registeredCourse in the dependency array
//Or have it in a ref
}, []);
// return(...)
}