React.js joi-browser validate according to database

704 Views Asked by At

I'm trying to validate an input using "joi-browser" schema. I want the input value to be valid only if it's similar to a description property inside any one of the objects inside an array that is in the state. The array comes from the database and is set on componentDidMount.

This is how the schema looks like so far:

orderItemsSchema = {
  id: Joi.number(),
  description: Joi.string().min(6).max(30).label("Description"),
  quantity: Joi.number().min(1).label("Quantity"),
};

schema = {
  custName: Joi.string().min(2).max(30).required().label("Customer Name"),
  orderItems: Joi.array()
    .label("orderItems")
    .required()
    .items(this.orderItemsSchema),
};

This is how the componentDidMount looks like:

componentDidMount = async () => {
    const { data } = await productService.getAllProducts();
    console.log("DBPRODUCTS B4 SET", this.state.dbProducts);
    if (data) {
      this.setState({ dbdata: data });
      console.log("dbdata after set", this.state.dbdata);
    }
  };

The array (dbdata) after it is set:

dbdata after set (21)
0: {createdAt: "2020-10-02T08:15:31.644Z", _id: "5f7713c5d1cee74e44af03a4", description: "Mazdar Swiffer mops", price: 8.49, inStorage: 73, …}
1: {createdAt: "2020-10-02T08:15:31.644Z", _id: "5f77142fd1cee74e44af03a5", description: "Taggba Clorox bleach", price: 3.49, inStorage: 534, …}
2: {createdAt: "2020-10-02T08:15:31.644Z", _id: "5f7715a8d1cee74e44af03a8", description: "Castle Supply Carpet cleaner", price: 9.99, inStorage: 168, …}
3: {createdAt: "2020-10-02T08:15:31.644Z", _id: "5f771601d1cee74e44af03a9", description: "Quickie All Purpose", price: 9, inStorage: 407, …}
4: {createdAt: "2020-10-02T08:15:31.644Z", _id: "5f77162cd1cee74e44af03aa", description: "All-Purpose Cleaner Spray", price: 4, inStorage: 413, …}
5: {createdAt: "2020-10-02T08:15:31.644Z", _id: "5f77167dd1cee74e44af03ab", description: "Mrs. Meyer’s Multi-Surface Cleaner", price: 3.99, inStorage: 153, …}
...

Instead of .min().max() I've tried using the joi-browser's valid() like this:

description: Joi.string()
  .valid(this.state.dbdata.map((item) => item.description))
  .label("Description"),

But instead of getting the error I expected I got: "Description" must be one of [ ]; which basically means the array is empty, meaning it wasn't set in componentDidMount yet right?

How can I solve this?

1

There are 1 best solutions below

0
On BEST ANSWER

Solved using componentDidUpdate to update the schema after componentDidMount has fetched the data from the DB.

orderItemsSchema = {};

schema = {};

//Fetch data from db and setState
componentDidMount = async() => {
  const {
    data: dbdata
  } = await productService.getAllProducts();
  if (dbdata) {
    this.setState({
      dbdata
    });
  }
};

//Update Joi schema after data has been fetched
componentDidUpdate = () => {
  this.orderItemsSchema = {
    id: Joi.number(),
    description: Joi.string()
      .valid(this.state.dbdata.map((item) => item.description))
      //Will be valid only if matches an item.description
      .label("Description"),
    quantity: Joi.number().min(1).label("Quantity"),
  };
  this.schema = {
    custName: Joi.string().min(2).max(30).required().label("Customer Name"),
    orderItems: Joi.array()
      .label("orderItems")
      .required()
      .items(this.orderItemsSchema),
    important: Joi.boolean().required(),
    totalPrice: Joi.number().required(),
  };
};