MiRAY
MiRAY

Reputation: 79

Simplify forEach in forEach React

I have a function where I have to return for each "subcontractor" its response for each selection criteria.

Subcontractor object contains a selectionCriteria object. selectionCriteria object contains an array of data for each selectionCriteria a user has responded to.

Each array item is an object, that contains files, id, request (object that contains info about selection criteria user is responding to), response (contains value of the response). Here is an example of how a subcontractor looks:

enter image description here

This is the function I come up with, but it's quite complex:

const { subcontractors } = useLoaderData<typeof loader>();
const { t } = useTranslation();
const submittedSubcontractors = subcontractors.filter(
  (s) => s.status === 'submitted'
);

const subcontractorsResponsesToSelectionCriteria: Array<ISubcontractor> = [];
let providedAnswersResponded: boolean | null = null;
let providedAnswersFiles: Array<IFile> | [] = [];
let providedAnswersRequiresFiles: boolean | null = null;

submittedSubcontractors.forEach((u) => {
  u.selectionCriteria.forEach((c) => {
    if (c.request.id === criteriaId) {
      if (c.response && 'answer' in c.response) {
        if (typeof c.response.answer === 'boolean') {
          providedAnswersResponded = c.response.answer;
        } else {
          providedAnswersResponded = null;
        }
      } else {
        providedAnswersResponded = null;
      }
      providedAnswersFiles = c.files;
      providedAnswersRequiresFiles = c.request.are_files_required;
      subcontractorsResponsesToSelectionCriteria.push(u as ISubcontractor);
    }
  });
});

How could I simplify this code by using .reduce() method, or maybe even better ideas?

Upvotes: 0

Views: 85

Answers (1)

Eduardo P&#225;ez Rubio
Eduardo P&#225;ez Rubio

Reputation: 1152

You should start working on reducing the level of nesting in your if/else like so:

function getProvidedAnswersResponded(response: any) {
    if (response && ('answer' in response) && (typeof response.answer === 'boolean')) {
        return response.answer;
    }

    return null;
}

submittedSubcontractors.forEach(u => {
    u.selectionCriteria.forEach(c => {
        if (c.request.id !== criteriaId) {
            return;
        }

        providedAnswersResponded = getProvidedAnswersResponded(c.response);
        providedAnswersFiles = c.files;
        providedAnswersRequiresFiles = c.request.are_files_required;
        subcontractorsResponsesToSelectionCriteria.push(u);
    });
});

The strategy followed was basically to invert the special cases (such as c.requet.id === criteriaId) and exit the function immediately.

Also, extracting the "provided answer responded" function seems atomic enough to move it to a separate block, giving it more verbosity about what that specific code block is doing.

Upvotes: 1

Related Questions