3

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

4
  • What is omit? If that's coming from a dependency, please include the import.
    – Jake Worth
    Commented May 31, 2019 at 4:55
  • Can you also post the omit method cannot get the full idea
    – Janith
    Commented May 31, 2019 at 4:59
  • @JakeWorth lodash's omit.
    – Hanz
    Commented May 31, 2019 at 5:49
  • @Janith I don't think that's the issue.
    – Hanz
    Commented May 31, 2019 at 5:50

2 Answers 2

2

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

1

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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.