简体   繁体   中英

reduce es6 missing nested array of object using spread

I've got a problem merging 2 sets of data by a condition. I've debugged for more than an hour but couldn't figure out why. I've created a sample below.

I have these 2 data:

const staticRockData = {
    rockTypes: [
      {
        supplierRockTypes: [
          {
            rockCodes: ["1"],
            match_id: "abc"
          },
          {
            rockCodes: ["2"],
            match_id: "abc"
          }
        ]
      }
    ]
  };

  const gatewayRockData = {
    match_id: "abc",
    rocks: [{ rock_type: "1", rates: [] }, { rock_type: "2", rates: [] }]
  };

I have this mapping logic:

let rockTypes = staticRockData.rockTypes;

  rockTypes = rockTypes.reduce((accum, rockType) => {
    const matchedSourceId = rockType.supplierRockTypes.some(
      o2 => o2.match_id === gatewayRockData.match_id
    );
    if (matchedSourceId) {
      gatewayRockData.rocks.forEach(rock => {
        const matchRockType = rockType.supplierRockTypes.some(o2 => {
          return o2.rockCodes.includes(rock.rock_type);
        });

        if (matchRockType) {
          console.log("rock.rock_type", rock.rock_type);
          rockType = {
            ...rockType,
            rock_type: rock.rock_type,
            rates: rock.rates
          };
        }
      });
    }

    accum = [...accum, { ...omit(rockType, "supplierRockTypes") }];

    return accum;
  }, []);

  return {
    rocks: rockTypes
  };

and I expected this:

rocks: [
       {
         rates: [],
         rock_type: "1"
       },
       {
         rates: [],
         rock_type: "2"
       }
     ]
   }

The current solution is missing this:

{ rates: [], rock_type: "1"} , I wonder where my mistake is.

Omit is lodash's omit function, but I don't think that's the culprit. I created a demo here:

https://codesandbox.io/s/condescending-platform-1jp9l?fontsize=14&previewwindow=tests

rockType is overwritten each repeat of the loop:

rockType = {
        ...rockType,
        rock_type: rock.rock_type,
        rates: rock.rates
      };

You should store the result in another variable this way:

...
let matchedRockTypes = [];
if (matchedSourceId) {
  gatewayRockData.rocks.forEach(rock => {
    const matchRockType = rockType.supplierRockTypes.some(o2 => {
      return o2.rockCodes.includes(rock.rock_type);
    });

    if (matchRockType) {
      console.log("rock.rock_type", rock.rock_type);
      matchedRockTypes.push({
        rock_type: rock.rock_type,
        rates: rock.rates
      });
    }
  });
}
return matchedRockTypes;
...

Here is the result: https://codesandbox.io/s/tender-ritchie-i0qkt

I don't know your exact requirement but I found out what is causing the issue The problem is in your reducer's forEach, which is fixed in version below:

rockTypes = rockTypes.reduce((accum, rockType) => {
    const matchedSourceId = rockType.supplierRockTypes.some(
      o2 => o2.match_id === gatewayRockData.match_id
    );
    if (matchedSourceId) {
      gatewayRockData.rocks.forEach(rock => {
        const matchRockType = rockType.supplierRockTypes.some(o2 => {
          return o2.rockCodes.includes(rock.rock_type);
        });

        if (matchRockType) {
          accum = [...accum, { rock_type: rock.rock_type,
            rates: rock.rates }];;
        }
      });
    }

    return accum;
  }, []);

More specifically line below in forEach:

if (matchRockType) {
          rockType = {
            ...rockType,
            rock_type: rock.rock_type,
            rates: rock.rates
          };
        }

Every time loop runs and it found match your it replaces your rockType content as it is an object not an array.

other solution takes an empty array outside forEach and push the contents in the inside if condition and spread it while returning.

Just saying you should consider refactoring your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM