I have a fields array with objects and I'm trying to loop this array:
fields: [
{
name: "seasonId",
type: "select",
label: "Season ID",
placeholder: "Select a season id...",
icon: "id",
value: "",
errors: "",
required: true,
disabled: true,
selectOptions: [],
},
{
name: "callTime",
type: "time",
label: "Scheduling Call Times",
placeholder: "Select a time...",
value: "",
errors: "",
required: true,
disabled: true,
},
];
To update its values AND append additional objects:
Incoming values:
"fieldValues": {
"callTimes": [
"5:45 pm",
"6:15 pm",
"6:30 pm",
"7:00 pm"
],
"selectedSeasonId": "20192020",
"seasonIds": [
"20192020",
"20202021",
"20212022",
]
}
Update field function:
const updateField = (currentField, fieldValues) => {
switch(currentField.name) {
case "seasonId":
return {
...currentField,
selectOptions: fieldValues.seasonIds,
value: fieldValues.selectedSeasonId,
disabled: false
};
case "callTime":
const callTimes = fieldValues.callTimes.map((value, key) => ({
...currentField,
name: key <= 0 ? "callTime" : `callTime-${Date.now()}`,
label: key <= 0 ? "Scheduling Call Times" : "",
value,
required: key <= 0,
disabled: false,
}));
return {
...callTimes
};
}
}
And then invoke the function above like so:
const updatedFields = fields.map(field => updateField(field, event));
However, I'm not getting the desired result.
Actual output:
[
'0': {
disabled: false
errors: ""
icon: "id"
label: "Season ID"
name: "seasonId"
placeholder: "Select a season id..."
required: true
selectOptions: ["20192020", "20202021", "20212022"]
type: "select"
value: "20192020"
},
'1': {
'0': {
disabled: false
errors: ""
label: "Scheduling Call Times"
name: "callTime"
placeholder: "Select a call time..."
required: true
style: {width: "100%"}
type: "time"
value: "5:45 pm"
},
'1': {
disabled: false
errors: ""
label: ""
name: "callTime-1565388886669"
placeholder: "Select a call time..."
required: false
style: {width: "100%"}
type: "time"
value: "6:15 pm"
},
'3': { ... },
'4': { ... }
}
];
Expected output:
[
'0': {
disabled: false
errors: ""
icon: "id"
label: "Season ID"
name: "seasonId"
placeholder: "Select a season id..."
required: true
selectOptions: ["20192020", "20202021", "20212022"]
type: "select"
value: "20192020"
},
'1': {
disabled: false
errors: ""
label: "Scheduling Call Times"
name: "callTime"
placeholder: "Select a call time..."
required: true
style: {width: "100%"}
type: "time"
value: "5:45 pm"
},
'2': {
disabled: false
errors: ""
label: ""
name: "callTime-1565388886669"
placeholder: "Select a call time..."
required: false
style: {width: "100%"}
type: "time"
value: "6:15 pm"
},
'3': { ... },
'4': { ... }
];
Any ideas on how I can update values and append additional objects to my fields array? The callTimes
array of string values within the field
object is dynamic (can contain 1 string or many), so I can't hard code anything.
const fields = [
{
name: "seasonId",
type: "select",
label: "Season ID",
placeholder: "Select a season id...",
icon: "id",
value: "",
errors: "",
required: true,
disabled: true,
selectOptions: [],
},
{
name: "callTime",
type: "time",
label: "Scheduling Call Times",
placeholder: "Select a time...",
value: "",
errors: "",
required: true,
disabled: true,
},
];
const fieldValues = {
"callTimes": [
"5:45 pm",
"6:15 pm",
"6:30 pm",
"7:00 pm"
],
"selectedSeasonId": "20192020",
"seasonIds": [
"20192020",
"20202021",
"20212022",
]
};
const updateField = (currentField, event) => {
switch(currentField.name) {
case "seasonId":
return {
...currentField,
selectOptions: fieldValues.seasonIds,
value: fieldValues.selectedSeasonId,
disabled: false
};
case "callTime":
const callTimes = fieldValues.callTimes.map((value, key) => ({
...currentField,
name: key <= 0 ? "callTime" : `callTime-${Date.now()}`,
label: key <= 0 ? "Scheduling Call Times" : "",
value,
required: key <= 0,
disabled: false,
}));
return {
...callTimes
};
}
};
const updatedFields = fields.map(field => updateField(field, event));
console.log(updatedFields);
Using reduce
instead of map
, I believe I am getting the right output:
const updateField = (result, currentField) => {
switch (currentField.name) {
case 'seasonId':
return [
...result,
{
...currentField,
selectOptions: fieldValues.seasonIds,
value: fieldValues.selectedSeasonId,
disabled: false
}
]
case 'callTime':
const callTimes = fieldValues.callTimes.map(...);
return [
...result,
...callTimes
]
}
}
const updatedFields = fields.reduce(updateField, [])
Since your callTime
case was returning multiple objects in an array, map
wouldn't work well in this case as you need to push/add these objects individually to the "final" array, hence this return
:
case 'callTime':
const callTimes = fieldValues.callTimes.map(...);
return [
...result,
...callTimes
]
Also, your callTimes
came out to be an array, and you tried to spread its items into an object:
case "callTime":
const callTimes = fieldValues.callTimes.map(...); // array
return {
...callTimes
};
This is why you were getting an unexpected/weird outcome.
Here's a demo with the fix:
Since you asked in the comments how to pass fieldValues
to the reducer function since they are being imported from another file, you can do the following:
const updateField = (result, currentField, fieldValues) => {...}
const updatedFields = fields.reduce(
(result, field) => updateField(result, field, fieldValues),
[]
)
Everything else stays the same.
Here's another demo: