'Duplicate of doc data created when trying to retrieve document data from firestore database in firebase
I've been tackling this issue for some days now but to no avail. I stored some images and other descriptions related to the images in my firestore database. But each time I try to retrieve the data from the database, it duplicates all the documents and then displays all the images twice after.
import React, {useEffect, useState} from 'react';
import styled from 'styled-components';
import { useParams } from 'react-router-dom';
import { getDoc, doc, onSnapshot } from 'firebase/firestore';
import db from '../firebase';
const Detail = () => {
const {id} = useParams();
const [detailData, setDetailData] = useState([]);
useEffect(() => {
// const getData = async () => {
// const movieRef = doc(db, "movies", id);
// try {
// setDetailData([]);
// const doc = await getDoc(movieRef);
// setDetailData(doc.data());
// console.log(detailData);
// return;
// } catch (e) {
// alert("Error getting cached document:", e);
// }
// };
// getData();
const docRef = doc(db, "movies", id);
onSnapshot(docRef, (doc) => {
if(doc.exists){
setDetailData(doc.data());
console.log(detailData);
} else{
console.log("no such document in firebase");
}
})
}, [id]);
return (
<Container>
<Background>
<img src={detailData.backgroundImg} alt={detailData.title} />
</Background>
<ImageTitle>
<img src={detailData.titleImg} alt={detailData.title} />
</ImageTitle>
<ContentMeta>
<Controls>
<Player>
<img src="/images/play-icon-black.png" alt="play button" />
<span>Play</span>
</Player>
<Trailer>
<img src="/images/play-icon-white.png" alt="trailer button" />
<span>Trailer</span>
</Trailer>
<AddList>
<span/>
<span/>
</AddList>
<GroupWatch>
<div>
<img src="/images/group-icon.png" alt="group icon" />
</div>
</GroupWatch>
</Controls>
<SubTitles>
{detailData.subTitle || 'Subtitles'}
</SubTitles>
<Description>
{detailData.description ||'Description'}
</Description>
</ContentMeta>
</Container>
);
}
const Container = styled.div`
position: relative;
min-height: calc(100vh - 250px);
overflow-x: hidden;
display: block;
top: 72px;
padding: 0 calc(3.5vw + 5px);
`;
const Background = styled.div`
left: 0px;
opacity: 0.8;
position: fixed;
right: 0px;
top: 0px;
z-index: -1;
img{
width: 100vw;
height: 100vh;
/* @media (max-width: 768px) {
object-fit: cover;
width: initial;
} */
}
`;
const ImageTitle = styled.div`
display: flex;
align-items: flex-end;
-webkit-box-pack: start;
justify-content: flex-start;
margin: 0px auto;
height: 30vw;
min-height: 170px;
padding-bottom: 24px;
width: 100%;
img{
max-width: 600px;
min-width: 200px;
width: 35vw;
}
`;
const ContentMeta = styled.div`
max-width: 874px;
`;
const Controls = styled.div`
align-items: center;
display: flex;
flex-flow: row nowrap;
margin: 24px 0px;
min-height: 56px;
`;
const Player = styled.button`
font-size: 15px;
margin: 0px 22px 0px 0px;
padding: 0px 24px;
height: 56px;
border-radius: 4px;
display: flex;
align-items: center;
cursor: pointer;
justify-content: center;
letter-spacing: 1.8px;
text-align: center;
text-transform: uppercase;
background: rgb(249, 249, 249);
border: none;
color: rgb(0, 0, 0);
img{
width: 32px;
}
&:hover{
background: rgb(198, 198, 198);
}
@media (max-width: 768px){
height: 45px;
padding: 0px 12px;
font-size: 12px;
margin: 0px 10px 0px 0px;
img{
width: 25px;
}
}
`;
const Trailer = styled(Player)`
background: rgba(0, 0, 0, 0.3);
border: 1px solid rgb(249, 249, 249);
color: rgb(249, 249, 249);
`;
const AddList = styled.div`
margin-right: 16px;
height: 44px;
width: 44px;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.6);
border-radius: 50%;
border: 2px solid white;
cursor: pointer;
span{
background-color: rgb(249, 249, 249);
display: inline-block;
&:first-child{
height: 2px;
transform: translate(1px, 0px) rotate(0deg);
width: 16px;
}
&:nth-child(2){
height: 16px;
transform: translateX(-8px) rotate(0deg);
width: 2px;
}
}
`;
const GroupWatch = styled.div`
height: 44px;
width: 44px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
background: white;
div{
height: 40px;
width: 40px;
background: rgb(0, 0, 0);
border-radius: 50%;
img{
width: 100%;
}
}
`;
const SubTitles = styled.div`
color: rgb(249, 249, 249);
font-size: 15px;
min-height: 20px;
@media (max-width:768px) {
font-size: 12px;
}
`;
const Description = styled.div`
line-height: 1.4;
font-size: 20px;
padding: 16px 0px;
color: rgb(249, 249, 249);
@media (max-width: 768px) {
font-size: 14px;
}
`;
export default Detail;
Now, the images contained inside this Trending row and other similar movie rows all get displayed twice when I go back to the home page:
import React from 'react';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { selectTrending } from '../features/movie/movieSlice';
const Trending = (props) => {
const movies = useSelector(selectTrending);
return (
<Container>
<h4>Trending</h4>
<Content>
{
movies && movies.map((movie, key) => (
<Wrap key={key}>
{movie.id}
<Link to={`/detail/` + movie.id}>
<img src={movie.cardImg} alt={movie.title} />
</Link>
</Wrap>
))
}
</Content>
</Container>
)
};
const Container = styled.div`
padding: 0 0 26px;
`;
const Content = styled.div`
display: grid;
grid-gap: 25px;
gap: 25px;
grid-template-columns: repeat(4, minmax(0, 1fr));
@media (max-width: 768px){
grid-template-columns: repeat(2, minmax(0, 1fr));
}
`;
const Wrap = styled.div`
padding-top: 56.25%;
border-radius: 10px;
box-shadow: rgb(0 0 0 / 69%) 0px 26px 30px -10px,
rgb(0 0 0 / 73%) 0px 16px 10px 10px;
cursor: pointer;
overflow: hidden;
position: relative;
transition: all 250ms cubic-bezier(0.25, 0.46, 0.45, 0.94) 0s;
border: 3px solid rgba(249, 249, 249, 0.1);
img{
inset: 0px;
display: block;
height: 100%;
object-fit: cover;
opacity: 1;
position: absolute;
transition: opacity 500ms ease-in-out 0s;
width: 100%;
z-index: 1;
top: 0;
}
&:hover{
box-shadow: rgb(0 0 0 / 80%) 0px 40px 58px -16px,
rgb(0 0 0 / 72%) 0px 30px 22px -10px;
transform: scale(1.05);
border-color: rgba(249, 249, 249, 0.8);
}
`;
export default Trending;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
