I have to admit, it the most strange bug that i saw in TypeScript-JavaScript (I got Model class in TypeScript and ReactJS Component in JS...) . I have a list of Promo Object, inside this one a property "_listCompte" which is a list of Compte Object.
The list of Promo is created by retrieving data from database, all works at this point
After that i got a forEach on listPromo and it works, but when i try to iterate with forEach on a listCompte it's looks like is empty.
ReactJS Component :
class DettesView extends Component{
state = {
loading: true,
activeItem: "DI4",
listPromo: []
};
componentDidMount() {
let listPromo = [];
FirebaseAPI.getDatabase().collection("Promo")
.onSnapshot((docSnapshot)=>{
docSnapshot.forEach((doc)=>{
const promoData = doc.data();
let promo = Promo.fromData({
nom: promoData.nom,
promoId: promoData.promoId
});
promoData.listCompte.forEach((compteRef)=>{
compteRef.get()
.then((doc)=>{
if(doc.exists){
let compte = Compte.fromData(doc.data());
promo.addCompte(compte);
}
}
)
});
listPromo.push(promo);
});
console.log("listPromo", listPromo);
this.setState({
loading: false,
status: true,
listPromo: listPromo
});
}, (error)=>{
this.setState({
loading: false,
status: false,
errorMessage: error.getMessage(),
errorCode: error.getCode()
});
});
}
toggleTabs = tab => () => {
if (this.state.activeTab !== tab) {
this.setState({
activeTab: tab
});
}
};
render() {
const {loading, listPromo} = this.state;
if(loading)
return (
<MDBContainer fluid>
<MDBRow center={true}>
<MDBCol size="2" className="mt-5">
<MDBCard>
<MDBCardBody>
<img src={gifLoading} alt="gif-loading"/>
<h1 className="mt-4 text-center">Loading...</h1>
</MDBCardBody>
</MDBCard>
</MDBCol>
</MDBRow>
</MDBContainer>
);
else if(this.state.status)
return (
<div className="classic-tabs">
<MDBNav classicTabs color="cyan">
{listPromo.map((value, index) => (
<MDBNavItem key={index}>
<MDBNavLink to="#" active={this.state.activeItem === value.nom} onClick={this.toggleTabs(value.nom)}>
{value.nom}
</MDBNavLink>
</MDBNavItem>
))}
</MDBNav>
<MDBTabContent
className="card"
activeItem={this.state.activeItem}
>
{listPromo.map((value, index) => {
console.log("value of property 'listCompte' in a 'Promo' object", value.listCompte);
console.log("size of property 'listCompte' in a 'Promo' object", value.listCompte.length);
return (
<MDBTabPane tabId={value.nom} key={index}>
<MDBTable hover>
<MDBTableHead>
<tr>
<th>Prénom</th>
<th>Nom</th>
<th>Promo</th>
<th>Dette</th>
</tr>
</MDBTableHead>
<MDBTableBody>
{value.listCompte.map((valueCompte, indexCompte) => {
console.log("compte", valueCompte);
return (
<tr key={indexCompte}>
<td>{valueCompte.nom}</td>
<td>{valueCompte.prenom}</td>
<td>{value}</td>
<td>{valueCompte.dette}</td>
</tr>
)
})}
</MDBTableBody>
</MDBTable>
</MDBTabPane>
)
})}
</MDBTabContent>
</div>
);
else
return (
<MDBContainer fluid>
<MDBRow center={true} className="mt-3">
<MDBCol size="6">
<MDBCard>
<MDBCardBody>
<img src={gifError} alt="gif-error" className="text-center img-fluid"/>
<h2>Erreur 😧 : {`${this.state.errorCode}`}</h2>
<h4>=> {`${this.state.errorMessage}`}</h4>
</MDBCardBody>
</MDBCard>
</MDBCol>
</MDBRow>
</MDBContainer>
);
}
}
(I already tried to use map instead of forEach but it didn't work). If someone got an idea, thanks
Promo TS-Class :
interface PromoData {
promoId: string;
nom: string;
}
class Promo {
private _nom: string;
private _promoId: string;
private _listCompte: Array<Compte>;
constructor(proId: string, nom: string) {
this._nom = nom;
this._promoId = proId;
this._listCompte = new Array<Compte>();
}
get listCompte(): Array<Compte> {
return this._listCompte;
}
addCompte = (value: Compte) => {
this._listCompte.push(value);
};
get promoId(): string {
return this._promoId;
}
set promoId(value: string) {
this._promoId = value;
}
get nom(): string {
return this._nom;
}
set nom(value: string) {
this._nom = value;
}
static fromData(promoData: PromoData): Promo{
return new this(
promoData.promoId,
promoData.nom
);
}
logError() : void {
console.log(this._listCompte);
this._listCompte.forEach((compte: Compte)=>{
console.log(compte)
})
}
}
And Compte TS-Class
interface CompteData {
promoId: string;
nom: string;
prenom: string;
dette: number;
isKefet: boolean;
compteId: string;
}
class Compte {
private _nom: string;
private _prenom: string;
private _dette: number;
private _promoId: string;
private _isKefet: boolean;
private _compteId: string;
constructor(compteId: string, nom: string, prenom: string, dette: number, isKefet: boolean, promoId: string) {
this._compteId = compteId;
this._nom = nom;
this._prenom = prenom;
this._dette = dette;
this._promoId = promoId;
this._isKefet = isKefet;
}
get compteId(): string {
return this._compteId;
}
set compteId(value: string) {
this._compteId = value;
}
get nom(): string {
return this._nom;
}
set nom(value: string) {
this._nom = value;
}
get prenom(): string {
return this._prenom;
}
set prenom(value: string) {
this._prenom = value;
}
get dette(): number {
return this._dette;
}
set dette(value: number) {
this._dette = value;
}
get isKefet(): boolean {
return this._isKefet;
}
set isKefet(value: boolean) {
this._isKefet = value;
}
static fromData(compteData: CompteData): Compte{
return new this(
compteData.compteId,
compteData.nom,
compteData.prenom,
compteData.dette,
compteData.isKefet,
compteData.promoId,
)
}
}
(All of my properties got getter and setter)
------- Additional Test -------
By adding a console.log of listPromo in render