Reputation: 413
I am learning to react-redux-firebase with the tutorial below.
I added sub-collection to collection. However, I don't know how to fetch subcollection. I need to get the original collection and its subcollection.
const mapStateToProps = (state, ownProps) => {
const id = ownProps.match.params.id;
const projects = state.firestore.data.projects;
const project = projects ? projects[id] : null
const subproject = //?
}
export default compose(
connect(mapStateToProps),
firestoreConnect([
{ collection: 'projects',
collection: 'subprojects'
}
])
)(ProjectDetails);
Upvotes: 1
Views: 497
Reputation: 4551
Edited answer:
I dont post all the steps here, but you need to follow the exact same steps you did with the projects collection, but for your subprojects collection, so make your subprojects reducer, add that to the rootReducer
...etc, so that the subprojects are in the global state, and you can link those to your component, the same as you did with the projects collection.
You would need to define if it will be in a separated reducer, in the project reducer itself so that it will figure in the state like this: const subprojects = state.firestore.data.projects.subprojects;
To compose your connector, you need to check redux-firestore repo where its adviced how to connect subcollections. Check the exmaple:
{
collection: 'cities',
doc: 'SF',
subcollections: [{ collection: 'zipcodes' }],
storeAs: 'SF-zipcodes' // make sure to include this
},
So that said, the mapStateToProps
would be as below:
const mapStateToProps = (state, ownProps) => {
// console.log(state);
const id = ownProps.match.params.id;
const subprojects = state.firestore.data.projects.subprojects;
const subproject = subproject ? subproject [id] : null
return {
subproject : subproject
}
}
export default compose(
connect(mapStateToProps),
firestoreConnect([{
collection: 'projects',
doc: 'YourDoc'
subcollections: [{ collection: 'subprojects' }],
storeAs: 'YorDoc-subprojects'
}])
)(YourSubProjectsComponent)
Not debugged code, just a proposal based on the repo example in case it might be helpfull for you to move on.
On the other hand I case if it is of any help, find below the code of the projectDetails
compenent, fetching the determined project from the firestore with the useState
hook. For your specific case, I believe that it would apply the same way, but querying your subprojects
collection. (typescript code). I post this, just in case you might be after a 'manual' fetch of your collection, instead of the direct binding with redux. If what you want is the direct bind with redux of your subproject collection you just can ommit the code below.
import { IFirebaseProject } from '../../store/types/projectTypes';
import { Redirect } from 'react-router-dom';
import moment from 'moment';
import firebase from 'firebase/app';
import { useState } from 'react';
async function getFbProject(id: string) {
const db = firebase.firestore();
const fbDoc = db.collection("projects").doc(id);
let project = {} as IFirebaseProject;
await fbDoc.get().then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
project = { ...doc.data()} as IFirebaseProject;
} else {
console.log(`Document does not exist ${id}`);
}
}).catch(function(error) {
console.log(`Error getting document: ${id}`, error);
});
return project;
}
function getProjectId():string {
const pathStr = window.location.pathname.toString();
const parts = pathStr.split("/");
const projStrIndex = parts.indexOf('project');
const projectId = parts[projStrIndex + 1];
return projectId;
}
const ProjectDetails = ({ project }: { project: IFirebaseProject } | { project: undefined }) => {
const [stateProject, setStateProject] = useState<IFirebaseProject | undefined>(project);
if (!firebase.auth().currentUser) return <Redirect to='/'/>
if (stateProject) {
return(
<div className="container section project-details">
<div className="card z-depth-0">
<div className="card-content">
<span className="card-title">{stateProject.title}</span>
<p>
{stateProject.content}
</p>
</div>
<div className="card-action grey lighten-4">
<div>{stateProject.authorFirstName} {stateProject.authorLastName}</div>
<div>{moment(stateProject.createdAt.toDate()).calendar()}</div>
</div>
</div>
</div>
)
} else {
//fetch project
const projectId = getProjectId();
getFbProject(projectId).then((project) => {
if (project) {
setStateProject(project);
}
});
return(
<div>
<p> Loading project... </p>
</div>
)
}
}
export default ProjectDetails;
Upvotes: 1