React final form split field values - javascript

I have a react and redux application with react final form where I have a field named 'cars' which is a select and on spy fire a submit event if data is dirty. All good with the values and stuff but I need to split that into the types so the form returns something like coupe: ['BMW'], sedan: ['Audi'] not just the field name with values such as cars: ['BMW', 'Audi']
{
type: "Coupe"
value: "BMW"
},
{
type: "Sedan"
value: "Audi"
}
Maybe anyone has a suggestion how to mutate that and when inside react final forms? or should it be done inside a reducer or saga?

Assuming you get your form data as
[
{
type: "Coupe",
value: "BMW"
}, {
type: "Sedan",
value: "Audi"
}
]
and you need to turn type value into the key name, so you get
[{ coupe: 'BMW'}, {sedan: 'Audi'}]
You may use Array.prototype.map() (inside your submit handler, or reducer, or wherever it works better for you):
const formData = [{type:"Coupe",value:"BMW"},{type:"Sedan",value:"Audi"}],
remappedData = formData.map(({type,value}) =>
({[type.toLowerCase()]: value}))
console.log(remappedData)
.as-console-wrapper{min-height:100%;}

Related

Is there a quicker way to copy a value in a key of data object to a new key in the same data object in javascript?

I'm experimenting with how I can make my code more concise when I have a piece of an array of objects received from an API endpoint. This is the initial variabel:
let stringOptionsOutlet = [];
Then I want to make a new key called "value". This is how I normally do (which I think is okey but I believe there must be some disadvantages in comparison with other techniques you might come up with):
stringOptionsOutlet = [...response.data.outlet]; // 1. this is the data I get from an API endpoint, I copy it with the spread operator
stringOptionsOutlet.map((v) => return { ...v, value: "" }; ); // 2. then I make the same new value in every single data object inside the array stringOptionsOutlet
Object.entries(stringOptionsOutlet).forEach((e) => {
e[1].value = e[1].id; // 3. copy the value of id to the new key
});
The data before I map the data:
[
{
label: "A1-1",
id: "1",
},
{
label: "B2-1",
id: "4",
},
]
After the mapping (step number 2 and number 3):
[
{
label: "A1-1",
id: "1",
value: "1",
},
{
label: "B2-1",
id: "4",
value: "1"
},
]
Could you also please explain the benefits and shortcomings of the techniques? Thank you.
What you're doing will work but there are certainly some unnecessary steps as written. There's no need to copy the API response data into an array and then change the array contents when you can map the API response itself.
// You can do steps 1 2 and 3 all in 1 .map()
const stringOptionsOutlet = response.data.outlet.map(v => {
return {
...v,
value: v.id
}
})
The downside of doing it all in 1 way is that if you want to do some more complex logic that single .map call could get very cluttered and maybe it'd be simpler to introduce a separate step, with the caveat that you'd then process the data a second time.
Try this:
stringOptionsOutlet.map((v) => ({ ...v, value: v.id }));

Map the values in object with the given value in react

I am new to the react, Here I have one array of object which is like
const bgStatus =
[{
Id: "809"
Name: "PRE"
Description: "PRE"
Value: "VP:PRE"
},
{
Id: "809"
Name: "CLO"
Description: "CLO"
Value: "VP:CLO"
},
{
Id: "809"
Name: "BU"
Description: "BU"
Value: "VP:BU"
}
]
Now , In this I have one method through which I get the value which is VP:PRE or VP:BU or VP:CLO
Now, I have the following function
getmsg = (bgSt, tobeChange, current) => {
return `Are you sure you want to change to ${tobeChange}? not possible to go ${current} `
}
Now, In this both the status tobeChange and current comes in a VP:PRE in this format. Now, I want to use the Description from that array for that value like for VP:PRE , it should be 'PRE' in the return value. Now ,
I have one solution which is like creating a key value map and then map it. But, I can not hard code that values over here.
So, and also don't want to use the includes or contains things.
Result which I want - When I am calling the function
getmsg this time in params I am passing , tobeChange is `"VP:PRE"`, current is "VP_BU" and bgStatus is the array of object.
Now in return I should get this message ,
`Are you sure you want to change to PRE not possible to go BU `
The values VP_PRE should get replaced with the description PRE
Well if you are always getting the two variables :
tobeChange=VP:something_to_change
current=VP:something
It has nothing to do with react it is javascript traitement
I suggest you use the function split here is an example :
getmsg = (tobeChange, current) => {
toChange=tobeChange.split(":")
tobeChange=toChange[1]
curr=current.split(":")
current=curr[1]
return `Are you sure you want to change to ${tobeChange}? not possible to go ${current} `
}
tobeChange="VP:something_to_change"
current="VP:something_current"
console.log(getmsg(tobeChange, current))

Send json in v-model vue

I have input with the name profile that is basically binded from data as:
data: function() {
return {
profile: {
phone: +123 123 123;
}
}
}
In the input I specify name as profile and v-model as profile.phone. It is sent to backend in the format:
name: profile, value: +123 123 123.
I obviously need to get also the information of the field specified - the phone. It is usually performed by sending name as profile.phone but the backend expects it as:
name: profile
value: {phone: +123 123 123}
The data are sent by sending all data from data. If I want to perform the reformatting that, how do I do that?
I recommend using re-declaring your object with let & this keywords. This will allow you to declare the owner of the function. so you can re-format as:
let profileValue = {
name: 'profile',
value: {
phone: this.profile.phone
}
}
You are sending the data to your back-end server using probably #click event that triggers your POST method? ...
Inside your method you need to construct your object like this...
let profileObj = {
name: 'profile',
value: {
phone : this.profile.phone
}
}

How to update the value of a single property within a state object in React.js?

So I have the following object structure:
const SamplePalette = {
id: 1,
name: "Sample Palette",
description: "this is a short description",
swatches: [
{
val: "#FF6245",
tints: ["#FFE0DB", "#FFA797"],
shades: ["#751408", "#C33F27"]
},
{
val: "#FFFDA4",
tints: ["#FFFFE1"],
shades: ["#CCCB83"]
},
{
val: "#BFE8A3",
tints: ["#E7FFD7"],
shades: ["#95B77E"]
}
]
}
Let's imagine that this object is managed by the state of my app like this:
this.state = {
currentPalette: SamplePalette,
}
My question is how would I go about updating the val property of a given swatch object in the swatches array? Or more generally - how do I only update pieces of this object?
I tried using the update helper as well as to figure out how Object.assign() works, however I've been unsuccessful and frankly can't really grasp the syntax by just looking at examples.
Also, since I'm going to be modifying this object quite a lot, should I look into maybe using Redux?
[EDIT]
I tried #maxim.sh suggestion but with no success:
this.setState(
{ currentPalette: {...this.state.currentPalette,
swatches[0].val: newValue}
})
Consider you have new new_swatches
I think the clearer way is to get array, update it and put back as:
let new_swatches = this.state.currentPalette.swatches;
new_swatches[0].val = newValue;
this.setState(
{ currentPalette:
{ ...this.state.currentPalette, swatches: new_swatches }
});
Also you have : Immutability Helpers or https://github.com/kolodny/immutability-helper
Available Commands
{$push: array} push() all the items in array on the target.
{$unshift: array} unshift() all the items in array on the target.
{$splice: array of arrays} for each item in arrays call splice() on the target with the parameters provided by the item.
{$set: any} replace the target entirely.
{$merge: object} merge the keys of object with the target.
{$apply: function} passes in the current value to the function and updates it with the new returned value.

Properly returning nested state with Object.assign

I'm working on a React/Redux application and for the most part, everything has been working smoothly.
Essentially, it's a todo application that has categorization built in.
I'm having trouble properly returning the full existing state in my reducer when the user adds a todo-item inside a category.
The redux state before I dispatch the ADD_ITEM action looks like this:
{
items: {
"HOME": [["Do laundry", "High Priority"],["Feed kids", "Low priority"] ],
"WORK": [["Get promotion", "High priority"],["Finish project", "Medium priority"] ],
"BOTH": [["Eat better", "Medium priority"],["Go for a run", "High priority"] ],
},
settings: {
Test: "test"
}
}
The user navigates to a category(pre-made, haven't implemented creating them yet) and can create a new todo-item with a name and a priority. This dispatches an action that returns an array like [category, name, priority].
Currently in my reducer, I have it where it is successfully adding the item, but it is emptying/overwriting all the existing categories.
My reducer looks like this:
case types.ADD_ITEM:
let cat = action.payload[0];
let name = action.payload[1];
let priority = action.payload[2];
return Object.assign({}, state, { items: { [cat]: [...state.items[cat], [name, priority]]}});
I've tried creating a new object first with all the combined items like so:
let combinedItems = Object.assign({}, state.items, { [cat]: [...state.items[cat], action.payload] });
If I console.log the above combinedItems, I get the exact object that I want items to be. However, I'm struggling to have the final object returned by the reducer to reflect that.
When I tried something like below, I got an object that contained combinedItems as a separate key inside items.
return Object.assign({}, state, { items: { combinedItems, [cat]: [...state.items[cat], [name, priority]]}});
Can anyone help me get my final redux state to contain all the existing categories/items + the user added one? I would really appreciate the help.
I think you should use objects in places where you have arrays. In your action payload, instead of:
[category, name, priority]
You can have:
{category, name, priority}
action.payload.category
I would make the same change with your todo items. Instead of:
[["Eat better", "Medium priority"], ... ]
You can have:
[{ name: "Eat better", priority: "Medium" }, ... ]
Now in terms of whether it's better to make items an object with category keys or an array of items that know its category... well I think the latter is better, that way if you get a single item, you don't need to go up to its parent to find out which category it belongs to. It would also make your problem a bit more manageable.
items: [
{
name: "Eat better",
priority: "Medium",
category: "Both"
}, ...
]
Putting this all together to solve your problem:
case types.ADD_ITEM:
let newItem = {
name: action.payload.name,
priority: action.payload.priority,
category: action.payload.category
}
return Object.assign({}, state, { items: [ ...state.items, newItem ] })
Whatever benefit you had before with categories as keys are trivial to reproduce with this structure.
Get all items in the HOME category:
this.props.items.filter(item => item.category === 'HOME')

Categories

Resources