Skip to content
Advertisement

Sorting an Objects keys/values by an array of objects the object is created from

So im generating a form for users of my application to fill out from an array of objects, each object has its own validation data….etc. This issue is when the user fills out the form and a new object is created from it to send to the back end, if the user fills out the form in order, the object is in the proper order, but if the user goes back and changes a value, the object is put out of order.
Original Object:

const formData = [
{
  name: 'One',
  validation: 'Number',
},
{
  name: 'Two',
  validation: 'Number',
},
{
  name: 'Three',
  validation: 'Number',
},
{
  name: 'Four',
  validation: 'Number',
}

The new Object is built with a handle change method
Object Handle:

  const [newForm, setNewForm] = useState({})

  const handleChange = (e) => {
    const { name, value } = e.target
    setNewForm({ ...newForm, [name]: parseFloat(Number(value).toFixed(2)) })
  }

Correct Object:

newForm = {
  One: 1,
  Two: 2,
  Three: 3,
  Four: 4,
}

Incorrect Object:

newForm = {
  Two: 2,
  One: 1,
  Four: 4,
  Three: 3,
}

I’m having a hard time trying to figure out a way of comparing the new form against the formData to make sure they stay in the proper order. If anyone could give some advice and help me out I’d appreciate it.

Answer

You are going to have a problem with your state, you may not be getting the previous state or newForm because of useState‘s asynchronous behavior. You are going to want to use an arrow function with a parameter for your previous state to get the previous state. Like this:

setNewForm((prevState) => ({
  ...prevState, [name]: parseFloat(Number(value).toFixed(2))
}))

Also here is some code from my github repo for comparing objects

/*
  Step 1: Check if both objects have same number of keys
*/

function keyNum(k1, k2) {
  return k1.length === k2.length ? true : false;
}

/*
  Step 2: put objects in the correct order
*/

function changeOrder(o1, o2) {
  /* This will check that all keys are equal and exist also
   * The first object's keys will look like this in array form: [a, b, c, d]
   * The next object's keys will probably be out of order relative to the first object's keys: [b, d, a, c]
   * The iterator will start on the first key of the first array and find it in the second, and create a new object in order
   * 
   * Example of first iteration:
   * 
   * (values of each key will obviously come with the key)
   * 
   *     ▼
   *    [a, b, c, d]
   *      
   *           ▼
   *    [b, d, a, c]
   * 
   *    new:
   *    [a]
   * 
   */

  let newObj = {};
  let equal = false;
  
  let baseObjKeys = Object.keys(o1);

  let returnObj = {
    newObj: "",
    equal: equal
  }

  for(let i = 0; i < baseObjKeys.length; i++) {
    if(typeof o2[baseObjKeys[i]] === 'undefined') {
      return returnObj;
    }

    newObj[baseObjKeys[i]] = o2[baseObjKeys[i]];
  }

  equal = true;

  returnObj = {
    newObj: newObj,
    equal: equal
  }

  return returnObj;
}

/*
  Step 3: Check if all the values with respect to their corresponding keys are equal
*/

function valEqu(o1, o2, k1) {
  for(let i = 0; i < k1.length; i++) {
    if(o1[k1[i]] !== o2[k1[i]]) {
      console.log('ran');
      return false;
    }
  }

  return true;
}

/*
  If all of these checks pass, the objects are equal.
*/

export default function compareObj (o1, o2) {
  let k1 = Object.getOwnPropertyNames(o1);
  let k2 = Object.getOwnPropertyNames(o2);

  let keyNumB = keyNum(k1, k2);
  let changeOrderB = changeOrder(o1, o2);
  // let keyEquB = keyEqu(k1, k2);
  let valEquB = valEqu(o1, changeOrderB.newObj, k1);

  if(keyNumB === true && changeOrderB.equal === true && valEquB === true) {
    return true;
  }

  return false;
}

Hopefully this helps.

Advertisement