reduce function with empty object is not working - javascript

I'm trying to create object from form elements. For some reason, it is throwing the error.
let allInputs = [...formData];
allInputs.pop(); //Remove submit button
return allInputs.reduce((userObj, data) => userObj[`${data.name}`] = data.value, {});
Error
userModel.js:17 Uncaught TypeError: Cannot create property 'last_name' on string ''

You need to return accumulator or in your case userObj in each iteration of reduce so your code should look like this.
allInputs.reduce((userObj, data) => (userObj[`${data.name}`] = data.value, userObj), {});

The problem is what you're returning the second time your reducer is called, not what you start with.
You are returning an assignment but should return an object.
(userObj, data) => userObj[`${data.name}`] = data.value // <-- this returns the result of the assignment
Something like this should work:
allInputs.reduce(
(userObj, data) => Object.assign(userObj, {
[data.name]: data.value
}),
{}
);
Note: as mentioned by Vic in the comment, no need for string interpolation, i.e. ${data.name} -> just data.name is enough.

Related

React Native - Manage CheckBox states

I want to make a Quiz App.
Questions are checked after user presses Submit button.
So questions are checked all at once in the end.
I need to save user choices (answers) for each question and then later check them on submit.
I was thinking about this:
let [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
let [userAnswers, setUserAnswers] = useState([] as any);
function answerClick(value: any, key: any) {
// console.log('answer clicked');
userAnswers[currentQuestionIndex][key] = value;
// TypeError: undefined is not an object (evaluating 'userAnswers[currentQuestionIndex][key] = value')
}
My checkbox for each possible answer in the question:
<BouncyCheckbox
key={index}
onPress={(value) => {
answerClick(value, index);
}}
text={answer.title}
/>
But I get
TypeError: undefined is not an object (evaluating 'userAnswers[current][key] = value')
on Answer click
What is setUserAnswers() equivalent of userAnswers[currentQuestionIndex][key] = value?
Why am I getting undefined error?
How to do this, please help my head hurts.
You are attempting to access a non existing index in the array.
userAnsqers = [];
currentQuestionIndex = 0;
// userAnswers[currentQuestionIndex] === undefined
What are you attempting to do is adding an {} to the array lazily (only when needed). This will work:
function answerClick(value: any, key: any) {
setUserAnswers(latest => {
const out = [...latest];
while (out.length <= currentQuestionIndex) out.push({});
out[currentQuestionIndex][key] = value;
return out;
})
}
There is nothing equivalent to setUserAnswers() for userAnswers[currentQuestionIndex][key] = value (see). You may find som custom hooks to manage arrays or build your own.
First off, the userAnswers should have the key and values of everything you're trying to change. The reason you're getting undefined is because you're trying to target an object in the userAnswers array which can't be found. Also, you are modifying the userAnswers state directly and that's really wrong. That's what the setUserAnswers is for. You can do this instead.
function answerClick(value: any, key: any) {
// console.log('answer clicked');
setUserAnswers([
...usersAnswers,
{[key]: [value]}
]);
}

How to resolve no-param-reassign error in a function

In a Node/JS function, I'm getting ESLint no-param-reassign the code is for update a candidate as follow
update(candidate) {
const { id } = candidate;
if (!id) {
throw new UserInputError('id is mandatory');
}
return this.tx(tableName)
.returning(Object.values(columnsByProperties))
.where('id', id)
.update(prepareCandidate(candidate))
.reduce((_, b) => camelcaseKeys(b), null)
.then(x => {
if (!x) {
throw new UserInputError(`Candidate "id" with ${id} is not found`);
}
x.preferredContact = x.preferredContactHours;
return x;
});
}
The error specifically is here Assignment to property of function parameter 'x'
.then(x => {
if (!x) {
throw new UserInputError(`Candidate "id" with ${id} is not found`);
}
x.preferredContact = x.preferredContactHours;
return x;
});
You can replace:
x.preferredContact = x.preferredContactHours;
return x;
With this:
return { ...x, preferredContact: x.preferredContactHours };
This way you return a new object instead of modifying the function's parameter.
Now, elaborating a bit. As the rule's documentation says:
Assignment to variables declared as function parameters can be misleading and lead to confusing behavior, as modifying function parameters will also mutate the arguments object.
"Confusing behavior" is to be understood as, for example, odd side effects. I remember wreaking havoc in an app because inside a function, I mutated an array that was passed as a parameter. The array was also mutated in the calling code which was bad. That's the kind of thing ESLint helps prevent!

Cannot assign to read only property of #<Object> using React with Recoil

I'm trying to update my state (an array of objects), but get the above error whenever I try to use .map or edit a clone of the state object.
React.useEffect(() => {
setUserMeasurements((oldUserMeasurements) => {
return oldUserMeasurements.map(nameAndMeasure => {
if (nameAndMeasure.name === name) { nameAndMeasure.measure = 60 }
return nameAndMeasure;
})
})
})
It doesn't seem to like it when I try the "nameAndMeasure.measure = 60" section of code, but I can't understand why. Can anyone explain?
I found that I could use this function to do what I was trying to get .map to do:
function replaceItemAtIndex(arr, index, newValue) { return [...arr.slice(0, index), newValue, ...arr.slice(index + 1)]; }
The .slice methods seem to create a new array, which satisfies javascript in a way that .map doesn't.

How would I programmatically call an object method? Like MyObject.XVariable(//some function)

I have an object, that takes input from an API call to fill it up.
let MyDog = {
Name: 'Dog',
}
let arrayFunctions;
fetchDogsFunctions(dogAPIUrl).then(res => {
//results is an array that has a list of functions the dog has, like //getStats(), or walkDog()
arrayFunctions = res;
})
Now I want to map through the array results and call the function on my dog like...
arrayFunctions.map(item => {
await MyDog.item(//Params)
})
How can I do this??
Where MyDog is set up from a file, and then depending on the array functions, for each function it programmatically fills in the call to the new function like MyDog.item where item is a variable in an array called "Walk()"
I assumed how your data might have structured. Pls take a look below and you might get the idea of how to call functions dynamically using "await"
const MyDog = {
funA(a) { return Promise.resolve('Function A called with parameter ' + a) }
, funB(b) { return Promise.resolve('Function B called with parameter ' + b) }
}
const arrayFunctions = ['funA', 'funB']
Promise.all(arrayFunctions.map(async (item, i) =>
await MyDog[item](++i))
)
.then(console.log)
I can't see any property name "item" in your MyDog Object
The answer is to do :
MyDog[item]()
within the loop.
I was asking the correct syntax to perform this operation

inside Array.push without a function call

I want to perform more logic before writing an element to an array:
tempDatensatz.push( () => {
var current = window.dataForDataTable[i].outbounds[key].updatedAt;
if (current) {
return current.toString();
} else {
return "".toString();
}
});
Getting the value from that array will be achieved like this:
tempDatensatz[0]()
But I want the same logic in it without having a function to call. I need a normal array, where I get a value like this:
tempDatensatz[0]
What can I do instead?
Updated
I published my project to gitHub, you can take a look if you need a better understanding :)
https://github.com/te2020/GoEuro/blob/master/GoEuro/Views/Home/Index.cshtml
Use an immediately invoked function instead of just a function:
tempDatensatz.push( (function(){
var current = window.dataForDataTable[i].outbounds[key].updatedAt;
if (current) {
return current.toString();
} else {
return "".toString();
}
})());
The function will be executed immediatly after it definition, returning the result. So push won't push a reference to that function but instead it will push it returned value (the result).
You can write a proxy as follows:
function makeProxy(array) {
return new Proxy(array, {
get(target, property) {
return !isNaN(property) ? target[property]() : target[property];
}
});
}
const tempDatensatz = [];
const useThisOne = makeProxy(tempDatensatz);
useThisOne.push(() => alert("Hi, Jane!"));
useThisOne[0];
Pushing/writing to the array will work as expected, but retrieving its elements will go through the get handler, which will execute the function.
You could just use an expression, like:
tempDatensatz.push(
(window.dataForDataTable[i].outbounds[key].updatedAt || '').toString();
);
For more complex expressions you can often use the ternary operator. For the above that would look like this:
tempDatensatz.push(
window.dataForDataTable[i].outbounds[key].updatedAt
? window.dataForDataTable[i].outbounds[key].updatedAt.toString()
: ''
);
Your code
When looking at the github code you linked to, you can do all that pushing with this "oneliner":
var tempDatensatz =
['companyId', 'mode', 'duration', 'outboundId', 'journeyId', 'departureTime',
'arrivalTime', 'stops', 'price', 'updatedAt', 'segments']
.map( prop => (window.dataForDataTable[i].outbounds[key][prop] || '').toString() );

Categories