ReactJS How to change value of object stored in state - javascript

All code will be below my question and explanation.
So what I am trying to do is update my state which is in a grandparent class, this is done for reasons to do with files, I am also using Material-UI for the text boxes.
And I'm also writing Redux without Redux, Because I can just if you see some strange things.
My grandparent class state looks like this:
state = {
value: 0,
application: {
ApplicationPK: '',
Person: [
{
PersonPK: '',
FullName: '',
TitleFK: '',
Forename: '',
MiddleNames: '',
Surname: '',
DateOfBirth: '',
HomeTelephone: '',
MobileTelephone: '',
EmailAddress: '',
LoanPurposeFK: '',
MaritalStatusFK: '',
Addresses: [
{
FlatNumber: '',
BuildingName: '',
BuildingNumber: '',
Street: '',
District: '',
Town: '',
County: '',
Postcode: '',
ResidentialStatusFK: '',
DateMovedIn: '',
IsCurrentAddress: '',
AddressPK: '',
},
],
Employment: [
{
EmploymentStatusFK: '',
Employer: '',
JobTitle: '',
Telephone: '',
MonthlyPay: '',
IsPaidByBACS: '',
PayFrequencyFK: '',
DayOfMonth: '',
DayOfWeek: '',
NextPayDate: '',
FollowingPayDate: '',
DateStarted: '',
Postcode: '',
EmploymentPK: '',
Website: '',
},
],
BankAccount: [
{
Name: '',
Sortcode: '',
AccountNumber: '',
IsAccountHolder: '',
IsJointHolder: '',
IsSoleAuthoriseDebits: '',
IsPrimary: '',
IsActive: '',
BankAccountPK: '',
},
],
},
],
},
};
I know its long but thats because it errors because mui text boxes dont like null values on load.
this is how im changing the state at the moment but its adding it as a value at the top level of the state and i want it to obviously replace the value that is inside person. this function is in the same class as the state obviously
handleChangeType = event => {
this.setState({ [event.target.name]: event.target.value });
}
and Finally the Mui Text Box looks like this:
<Input
defaultValue={this.props.state.application.Person[0].Forename}
className={classes.input}
onChange={this.props.handleChangeType}
name="Forename"
inputProps={{
'aria-label': 'Description',
}}
/>
TL:DR: How do i update the correct value in the state

I know its long but thats because it errors because mui text boxes dont like null values on load.
To avoid initializing a bunch of empty strings everywhere, you could just do:
defaultValue={((this.props.state.application || {}).Person[0] || {}).Forename || ""}
As per updating the correct state variable, I would use a different handler for each category. You must also bear in mind that your state variable here is the Person array. If you want to update anything within it, you need to pass a new array to the state. Finally, you seem to want to be able to have multiple users inside your Persons array, but your event handlers aren't given any info of which user you want to update field X or Y.
For example:
handleChangeType = (userIndex, name, event) => {
let person = Object.assign({}, this.state.Persons[userIndex]); //shallow-copy
person[name] = event.target.value
this.setState({Person: person });
}
For each object or array that's nestled, you'll need to create a copy, change the copy and then replace the original with the copy.

Related

How can I update state while preserving immutability?

I'm not using the immutable library and I'm working on it.
I want to update the key and value values ​​of mapTable without changing the constant of PRICE_OPTION2_STATE.
I'd appreciate it if you could tell me how.
I have posted the results of the problem and the results I want.
//my code
tableData['option2Price'] = 50000;
const mapCopy = { ...copyState };
let tableCopy = { ...mapCopy[currentTableIndex].mapTable[findTableIndex] };
tableCopy = tableData;
mapCopy.tableCopy = tableCopy;
// problem
console.log(PRICE_OPTION2_STATE);
// initstate
const PRICE_OPTION2_STATE = [
{
id: 1,
option2Name: '',
option2LeftSelect: 'sell',
mapTable: [
{
tableId: 1,
flag: true,
option2Value: '',
option2Price: '',
discountInput2: '',
discountOption2: 'won',
option2Payment: '',
option2Tax: '',
option2settlementAmount: '',
option2RightSelect: 'sell',
},
],
},
];
PRICE_OPTION2_STATE => problem console result
[
{
id: 1,
option2Name: '',
option2LeftSelect: 'sell',
mapTable: [
{
tableId: 1,
flag: true,
option2Value: '',
option2Price: '',
discountInput2: '',
discountOption2: 'won',
option2Payment: '50000',
option2Tax: '',
option2settlementAmount: '',
option2RightSelect: 'sell',
},
],
},
]
result i want
[
{
id: 1,
option2Name: '',
option2LeftSelect: 'sell',
mapTable: [
{
tableId: 1,
flag: true,
option2Value: '',
option2Price: '',
discountInput2: '',
discountOption2: 'won',
option2Payment: '',
option2Tax: '',
option2settlementAmount: '',
option2RightSelect: 'sell',
},
],
},
]
I'll assume copyState is a reference to PRICE_OPTION2_STATE or at least is some sort of (shallow) copy of it. So to copy it, you should:
not use object spread notation at the top level, since it is an array.
not leave it at a shallow copy, but copy it deeply. So you'll also need to map the inner array and copy the objects it has.
Here is some inspiration:
// Assuming copyState has the structure of PRICE_OPTION2_STATE
// Get a deep copy
const mapCopy = copyState.map(({mapTable, ...rest}) => ({
...rest,
mapTable: mapTable.map(obj => ({...obj}))
}));
// Now this assignment will not impact copyState / PRICE_OPTION2_STATE
mapCopy[currentTableIndex].mapTable[findTableIndex] = tableCopy;

Unable to deep clone [duplicate]

This question already has answers here:
How to Import a Single Lodash Function?
(10 answers)
Closed 1 year ago.
I want to make a copy of an object.
Following that, I plan to modify values within the copy but these
modifications should not affect the original object.
Thus I want to make a clone and presently using lodash's deepClone.
But it keeps throwing the following error:
Error!Object(...) is not a function
There is no function within my object. It is just in following structure.
They are just key values where values are either strings or booleans.
const myOriginalObject {
mainKey : {
isMobile: true,
data: {
id: '',
header: '',
flag: '',
desc1: '',
desc2: '',
logo: {
src: '',
alt: '',
},
img: {
src: '',
alt: '',
},
}
}
}
Just to test it out created a random object as follows.
And even this throws same error.
const myOriginalObject = {
b: '',
c: ''
}
This is the implementation to deep copy. myOriginalObject can be either one of above objects.
import { cloneDeep } from 'lodash/cloneDeep';
const myClone = cloneDeep(myOriginalObject);
What am I doing wrong? Pls advice. Thanks.
UPDATE:
My lodash version from package.json
"lodash": "^4.17.20",
Error:
render had an error: TypeError: Object(...) is not a function
try with this
const myOriginalObject {
mainKey : {
isMobile: true,
data: {
id: '',
header: '',
flag: '',
desc1: '',
desc2: '',
logo: {
src: '',
alt: '',
},
img: {
src: '',
alt: '',
},
}
}
}
const newObj = JSON.parse(JSON.stringify(myOriginalObject));
Now make any changes to newObj it will not reflect to myOriginalObject;

How to acess child object via param

I have an Vue app with this data:
data: {
personal: {
email: '',
first_name: '',
last_name: '',
password: '',
password_confirmation: '',
phone: '',
work_email: ''
},
company: {
address: '',
annual_revenue: null,
city_id: null,
country: 'BRA',
company: '',
company_city_document: '',
company_document: '',
company_legal_name: '',
position: '',
state_id: null,
vat: null,
website: '',
work_phone: '',
zipcode: ''
}
}
I want to acess the child object from my mixin, but when i send the propertie via param i get undefined on mixin, im sending like this:
<TextField
#input="checkFormInvalidity('personal.first_name')"
id="first_name"
label="Nome"
/>
When user types anything vue will emit what he typed, in my mixin is a simple verifying method like this:
checkFormInvalidity (field) {
field
? this.$v.data[field].$touch()
: this.$v.$touch()
return field
? !!this.$v.data[field].$invalid
: !!this.$v.$invalid
}
When i do:
console.log(this.data[field])
I receive "undefined" because i don't know how to access the child object from data in that case would be "data.personal.first_name".
If i receive in param "field" only "personal" i can see all data properties.

Generate valid v-model value using dot notation string as object reference to the data

Basically i've made proyxy-component which renders different components based on what the :type is and it works great. The point is that I create a schema of the form controls and a separate data object where the data from the form controls is stored. Everything is working good but i have a problem when formData object contains nested objects.
In my example test.test1
How can i make the v-model value dynamic which is generated based on what the string is.
My Compoennt
<proxy-component
v-for="(scheme, index) in personSchema.list"
:key="index"
:type="scheme.type"
:props="scheme.props"
v-model="formData[personSchema.prefix][scheme.model]"
v-validate="'required'"
data-vv-value-path="innerValue"
:data-vv-name="scheme.model"
:error-txt="errors.first(scheme.model)"
></proxy-component>
Data
data() {
return {
selectOptions,
formData: {
person: {
given_names: '',
surname: '',
sex: '',
title: '',
date_of_birth: '',
place_of_birth: '',
nationality: '',
country_of_residence: '',
acting_as: '',
test: {
test1: 'test',
},
},
},
personSchema: {
prefix: 'person',
list: [
{
model: 'given_names',
type: 'custom-input-component',
props: {
title: 'Name',
},
},
{
model: 'surname',
type: 'custom-input-componentt',
props: {
title: 'Surname',
},
},
{
model: 'test.test1',
type: 'custom-input-component',
props: {
title: 'test 1',
},
},
{
model: 'sex',
type: 'custom-select-component',
props: {
title: 'Sex',
options: selectOptions.SEX_TYPES,
trackBy: 'value',
label: 'name',
},
},
],
},
};
},
I would recomment you to write a vue-method (under the data section) that returns the object for v-model
v-model="resolveObject(formData[personSchema.prefix][scheme.model])"
or
v-model="resolveObject([personSchema.prefix] , [scheme.model])"
There you can do handle the dot-notation and return the proper nested property.
I don't think it's possible directly with v-model, you can take a look at:
https://v2.vuejs.org/v2/guide/reactivity.html
Maybe the best solution would be use a watch (deep: true) as a workaround.
(I would try first to use watch properties inside formData[personSchema.prefix][scheme.model].)

JSON.stringify is not storing object property values

I have the following object in my code:
/* ======= Model ======= */
model = {
workout: [
{
name: '',
email: '',
workouttype: '',
workoutplan: '',
excardio: '',
exstrength: '',
excore: '',
exhiit: '',
validworkout: false,
hasexercises: false
}
]
};
When I try to save the object to localstorage, all the properties are empty.
Here is how I'm storing my object:
saveWorkout: function () {
var key = "Workout",
item = JSON.stringify(model.workout);
localStorage.setItem(key, item);
}
Thanks!

Categories