I'm trying to save objects to an array, but I can't do it, the old state is deleted. I have two states in my component, from two different forms, the first form is just text and I get the data by "handleChange", but the second form is several objects that I want to store in an array that I get by "handleChangeArray".
const [formCompra, setFormCompra] = useState({
name: '',
lastName: '',
items: []
});
const [restForm, setRestForm] = useState();
const handleChage = (e) => {
const { name, value } = e.target;
setFormCompra({
...formCompra,
[name]: value
})
}
const handleChangeArray = (e) => {
const { name, value } = e.target;
setRestForm({
...restForm,
[name]: value
})
}
const handleSubmit = () => {
let newData = {
name: formCompra.name,
lastName: formCompra.lastName,
items: [...formCompra.items, restForm] //probably the error is here
}
console.log(newData)
}
As I mention, it is not possible to save the data in the array, I appreciate any help.
You can use the current state to set a new value, keeping all other values:
setState((current) => ({
...current,
key: newValue
}));
I think the issue may be that spread syntax only shallow copies the array, so in
const handleSubmit = () => {
let newData = {
name: formCompra.name,
lastName: formCompra.lastName,
items: [...formCompra.items, restForm] //probably the error is here
}
items is a copy of an array that points to all the original objects.
try
let newData = {
name: formCompra.name,
lastName: formCompra.lastName,
items: [...formCompra.map(x=>{...x}), {...restForm}] //probably the error is here
}
Related
I have array of objects where i need to an key value
useState :
const [row, setRow] = useState([{ nameofthework: "", schedulerefNo: "", unitprice: "", qty: "", uom: "", gst: "", total: "" }]);
The form input change function
const handleInputChange = (e, index) => {
const { name, value } = e.target;
const list = [...row];
list[index][name] = value;
setRow(list);
console.log(row); // Prints out the each row object into and array of objects
};
const handleQty = (e) => {
const scheduleNumberForQuantity = e.target.value;
projectScheduleNumber?.filter((v) => {
if(v["Schedule No"] === scheduleNumberForQuantity ) {
setScheduleQuantity(v["LOA Qty"]); // return only integer example 1000
}
})
}
How to add handleQty value to row state ?
I think that you need declare the state like a function instead of array of objects key value. It will allow setRow to be managed as function in any moment inside of the function component.
const [row, setRow] = useState<any>();
With <any> allows save anything. So you could apply a strong type like:
const [row, setRow] = useState<()=>void>();
or in you case
const [row, setRow] = useState<(e: any)=>void>();
I hope it is useful for you.
In my post request I need to pass an array with an object inside it.
when I tried to add new properties inside an object its adding.
but when I tried to add when an object is present inside an array its not adding.
I have sportsvalues as array const sportsValues = [{ ...values }];
I am trying to build something like this, so that I can pass in the api
[
{
"playerName": 3,
"playerHeight": 1
}
]
can you tell me how to fix it.
providing my code snippet below.
export function sports(values) {
const sportsValues = [{ ...values }];
sportsValues.push(playerName:'3');
console.log("sportsValues--->", sportsValues);
// sportsValues.playerName = 3//'';
// sportsValues.playerHeight = 1//'';
console.log("after addition sportsValues--->", sportsValues);
console.log("after deletion sportsValues--->", sportsValues);
return dispatch => {
axios
.post(`${url}/sport`, sportsValues)
.then(() => {
return;
})
.catch(error => {
alert(`Error\n${error}`);
});
};
}
Since sportsValues is an array of objects, you can push new object into it. Check out code below.
const sportsValues = [];
sportsValues.push({
playerName:'3',
playerHeight: 1,
});
console.log(sportsValues);
I don't fully understand what you're trying to do, but here's some pointers:
If you're trying to update the object that's inside the array, you first have to select the object inside the array, then update it's attribute:
sportsValues[0].playerName = 3
although, I recommend building the object correctly first, then passing it to the array, it makes it a little easier to understand in my opinion:
const sportsValues = [];
const firstValue = { ...values };
firstValue.playerName = '3';
sportsValues.push(firstValue);
or
const firstValue = { ...values };
firstValue.playerName = '3';
const sportsValues = [firstValue];
or
const sportsValues = [{
...values,
playername: '3',
}];
if you're trying to add a new object to the array, you can do this:
const sportsValues = [{ ...values }];
sportsValues.push({ playerName: '3' });
etc...
Array.push adds a new item to the array, so in your code, you're going to have 2 items because you assign 1 item at the beginning and then push a new item:
const ar = [];
// []
ar.push('item');
// ['item']
ar.push({ text: 'item 2' });
// ['item', { text: 'item 2' }]
etc...
export function sports(values) {
const sportsValues = [{ ...values }];
sportsValues.push(playerName:'3');
let playerName='3'
sportsValues.playerName= playerName; // you can bind in this way
console.log("sportsValues--->", sportsValues);
return dispatch => {
axios
.post(`${url}/sport`, sportsValues)
.then(() => {
return;
})
.catch(error => {
alert(`Error\n${error}`);
});
};
}
const fields = ['email', 'password'];
const objFields = {};
fields.forEach(value => {
objFields[value] = '';
});
console.log(objFields);
// Outputs {email: "", password: ""}
I want to achieve the same result but without having to initialize an empty object.
Actually my case is that I want to set initial state of a React component.
class App extends Component {
fields = ['email', 'password'];
state = {
fields: // the one liner code here that should return the object created from fields array,
};
...
expected result would be
// state = {fields: {email: "", password: ""}}
Whenever you're looking for reducing an array of values to one value, you're looking for .reduce()
state = {
fields: fields.reduce((acc, key) => ({...acc, [key]: ''}), {}),
};
You could map objects and assign all to a single object.
const
fields = ['email', 'password'],
object = Object.assign({}, ...fields.map(key => ({ [key]: '' })));
console.log(object);
In modern browsers, or by using polyfills, you can use Object.fromEntries() to create an object from an array, using the array's values as keys/properties, and fill the object's values with a default.
const fields = ['email', 'password'];
const result = Object.fromEntries(fields.map(value => [value, '']));
The result is {email: "", password: ""}.
You need to transform your array which contains keys into a real object.
To do it you have many possibilites, but you still have to do something, there is no magical trick.
My favorite soluce is to use a function to insert into your Utilitary class. So it's easy to read and re-usable.
number 1 : The function
function initializeKeys(keys, initialValue, object) {
return keys.reduce((tmp, x) => {
tmp[x] = initialValue;
return tmp;
}, object);
}
const objFields = initializeKeys(['email', 'password'], '', {
otherKey: 'a',
});
console.log(objFields);
number 2 : The forEach
const fields = ['email', 'password'];
const objFields = {};
fields.forEach(value => {
objFields[value] = '';
});
console.log(objFields);
number 3 : The reduce
const fields = ['email', 'password'];
const objFields = {
...fields.reduce((tmp, x) => {
tmp[x] = '';
return tmp;
}, {}),
};
console.log(objFields);
I need to add an id number to the nested array in data called action. The code I'm using is:
const { data } = this.state
const newData = Object.assign([...data.action], Object.assign([...data.action],{0:'id' }))
but this code is not working. The result I am looking for is:
{id:1 action: "user...}
You can just use the spread operator.
const newData = {
...data,
action: {
...data.action,
id: 1
}
};
If action is an array, you can try something like this:
const newAction = data.action.map((actionItem, index) => ({
...actionItem,
id: index + 1
}));
const newData = {
...data,
action: newAction
};
I have a state object that looks like this.
this.state = {
formValues: {},
};
After some processing, formValues contains the following.
this.state = {
formValues: {
q1: value 1,
q2: value 2
},
};
Now i have q3 inside formValues which is an array of values. When i try to push the value like as follows
let q3 = e.target.name,
arrayValues = [1,2,3]
formValues[q3].push(arrayValues)
I am getting the following error while submitting the data
Uncaught Error: A state mutation was detected between dispatches
It looks like there is a problem with pushing data into array. Any idea on how to fix this?
You need to create a copy and update the state with setState instead of direct state mutation with push.
this.setState(prevState => ({
formValues: {
...prevState.formValues,
[q3]: prevState.formValues[q3].concat(arrayValues),
},
}));
assuming that you always want to push to your array such as in your use case:
const { formValues } = this.state
const arrayValues = [1,2,4]
const newFormValues = { ...formValues, q3: [...formValues[q3], arrayValues]}
this.setState({ formValues: newFormValues })
but much better if you control directly the value of q3:
const { formValues } = this.state
const arrayValues = [1,2,4]
const newFormValues = { ...formValues, q3: arrayValues}
this.setState({ formValues: newFormValues })