I have a array-object which should look something like this and is used to create a form
const questions = [
{
condition_action: "selected",
label: "What is your name?",
question_type: "free_text",
required: true,
},
{
condition_action: "selected",
label: "Where do you live?",
question_options: [
{
label: "India",
},
{
label: "china",
},
{
label: "japan",
},
],
question_type: "single_answer",
required: false,
},
];
Now, When user is done creating the form, I have to validate the data and add a key name order
in the above snippet (more below) to array-object (main array and question_options)
For validation, There are two conditions
- Main array-object should have a label (if not throw error).
- Question option should have at-least 1 item and the label inside it can't be empty
Basically, question_options is for multiple-select and single select drop down. So question_option should only contain value if question_type
key in the above snippet is single_answer
or multiple_answer
The backend api also require attribute order
on the main question array and question_options array (yeah even though it's an array we could determine the order through index)
So this is the code I wrote
const validateAndFormatdata = (questions) => {
// we will change this to true if error exist and send it at return of this function
let errorsExsist = false
// we are formating data here, if error exist while validation, we change flag
const formatedData = (questions || []).map((question, index) => {
// delete all previous errors since we are iterating and we don't care about our previous errors
if (Object.prototype.hasOwnProperty.call(question, "errors")) {
delete question.errors
}
// There can be more than one thing wrong, hence using an array
const newErrors = []
// if label does not have value, add it it in errors array
if (question.label === "") {
newErrors.push(errorReasons.missingLabel)
}
if (
question.question_type === "multiple_answer" ||
question.question_type === "single_answer"
) {
const questionOptions = _.filter(question.question_options, "label").map(
(option, position) => {
return {
...option,
order: position
}
}
)
// if question optiond does not have single item, add it it in errors array
if (questionOptions.length < 1) {
newErrors.push(errorReasons.noOption)
} else {
question.question_options = [...questionOptions]
}
} else if (Object.prototype.hasOwnProperty.call(question, "question_options")) {
// remove question otpions of question type isn't single or mult-text
delete question.question_options
}
if (newErrors.length > 0) {
errorsExsist = true
question.errors = newErrors
}
return { ...question, order: index }
})
return {
errorsExsist,
data: formatedData
}
}
Question: I was wondering if someone can share review, optimisation and suggestions (including naming)?
1 Answer 1
I have made some changes and added comments for each change.
// add the default array here ------------↓
const validateAndFormatdata = (questions = []) => {
let errorsExist = false, // <- typo in exist
// in case you want to add new types
optionTypes = new Set(["multiple_answer", "single_answer"]);
// no need to check for || [] because default is added
// remove the errors property here itself by using destructuring
const formattedData = questions.map(({ errors, question_options, ...question }, index) => {
// because of the destructuring, question is a new object.
// So, will not mutate the original object
question.order = index;
const newErrors = []
// checks if label exists and if it is an empty string
if (!question.label) {
newErrors.push(errorReasons.missingLabel)
}
if (optionTypes.has(question.question_type)) {
const questionOptions = question_options
.filter(q => q.label)
.map((option, order) => ({ ...option, order }));
// === 0 is much more clearer to read
if (questionOptions.length === 0) {
newErrors.push(errorReasons.noOption)
} else {
// no need for [...]. It's a new array
question.question_options = questionOptions
}
}
// no need for delete question.question_options because it is destructured
if (newErrors.length > 0) {
errorsExist = true
question.errors = newErrors
}
return question;
})
return {
errorsExist,
data: formattedData
}
}