Luca Baxter Luca Baxter - 23 days ago 11
React JSX Question

React, Mobx, Firebase conditional rendering

i have a problem with a basic conditional rendering.
basically i have this Store:

import { ObservableMap, observable, action, computed } from 'mobx';
import fb from '../firebase';

class ProductStore {
@observable products = [];

constructor() {
fb.products.on('value', (snapshot) => {
this.products = [];
snapshot.forEach((child) => {
this.products.push({
id: child.key,
...child.val()
});
});
});
}

@action addProduct = (product) => {
fb.products.push(product);
}

@action removeProduct = (product) => {
fb.products.child(product.id).set({});
}

@computed get totalProducts() {
return this.products.length;
}


}

const store = new ProductStore();
export default store ;


I'm trying to render a message if i don't have any product stored on firebase, and the loading... message, if i'm getting the data from firebase, so i'm doing this now:

const ProductList = (props) => {

const renderView = () => {
if(props.products.length){
return props.products.map((product,index) => <Product key={index} product={product} removeProduct={props.removeProduct}/>);
}else{
return <p>Loading...</p>
}
}

return (
<div className="product-list">
{console.log(props.products)}
{renderView()}
</div>
)
}


how can i print the message "products not found" if i don't have any data on firebase? cause in the beginning i initialize the products observable to an array, then react show the loading message and after that it loads in the data, but then if i remove all the data on firebase of course it show the loading message.

Answer Source

You could just extend your ProductStore with a isLoading field:

class ProductStore {
  @observable products = [];
  @observable isLoading = true;

  constructor() {
    fb.products.on('value', (snapshot) => {
      const products = [];

      snapshot.forEach((child) => {
        products.push({
          id: child.key,
          ...child.val()
        });
      });

     this.products.replace(products);
     this.isLoading = false;
    }, (error) => {
      this.isLoading = false;
    });
  }

  @action addProduct = (product) => {
    fb.products.push(product);
  }

  @action removeProduct = (product) => {
    fb.products.child(product.id).set({});
  }

  @computed get totalProducts() {
    return this.products.length;
  }
}

And use this in conjunction with products.length in your view:

const ProductList = ({ isLoading, products }) => {
  let result;

  if (isLoading) {
    result = <p>Loading...</p>;
  } else if (products.length === 0) {
    result = <p>Products not found</p>;
  } else {
    result = products.map((product, index) => <Product key={index} product={product} removeProduct={props.removeProduct}/>);
  }

  return (
    <div className="product-list">
      {result}
    </div>  
  );
}