I want to overwrite the array if the keys are the same. And push if keys are different.
From this:
const fieldData = [
{
"field_1": {
"value": "oldValue"
},
"field_2": {
"value": "oldValue"
}
}
];
const [data, setData] = useState(fieldData);
const pushData = (newData) => {
setData(current => [...current, newData]);
}
The result if the keys are the same:
{
"field_1": {
"value": "newValue"
},
"field_2": {
"value": "oldValue"
}
}
The result if the keys are diffrent:
{
"field_1": {
"value": "newValue"
},
"field_2": {
"value": "oldValue"
},
"field_3": {
"value": "newValue Field 3"
}
}
I would recommend you to work with a different data structure.
Change your array and work with a dictionary.
const fieldData = {
"field_1": {
"value": "oldValue"
},
"field_2": {
"value": "oldValue"
}
}
const [data, setData] = useState(fieldData);
const pushData = (newData) => {
setData(current => ({...current,...newData}));
}
In this case, if you have a new [key, value] it will be added to your object. Otherwise the value will be overridden
Related
I want to show the key and value from nested object with data :
const obj = {
"success": true,
"data": {
"data1": {
"label": "label1",
"value": "value1"
},
"data2": {
"label": "label2",
"value": "value2"
}
}
}
And want to show the data to object like this:
{data1: "value1", data2: "value2"}
I already try this:
const init = Object.entries(obj.data).map(([key, value]) => {
const data = `${key}: ${value.value}`;
return data;
});
But I got wrong format.
Use the reduce function
const obj = {
"success": true,
"data": {
"data1": {
"label": "label1",
"value": "value1"
},
"data2": {
"label": "label2",
"value": "value2"
}
}
}
const list = Object.keys(obj.data).reduce((acc, key) => {
acc[key] = obj.data[key].value
return acc
}, {})
console.log( list)
You could use Array#reduce for it.
const obj = {success:true,data:{data1:{label:"label1",value:"value1"},data2:{label:"label2",value:"value2"}}};
const res = Object.entries(obj.data).reduce((acc, [key, obj]) => ({
...acc,
[key]: obj.value,
}), {});
console.log(res);
I am trying to update my product attributes and i came to a solution only for one attribute.
this is my carrtItems state
this.state = {
cartItems: [],
selectedAttributes: []
Json Object
{
"__typename": "Product",
"name": "iPhone 12 Pro",
"inStock": true,
"attributes": [
{
"__typename": "AttributeSet",
"id": "Capacity",
"name": "Capacity",
"type": "text",
"items": [
{
"__typename": "Attribute",
"id": "512G",
"value": "512G"
},
{
"__typename": "Attribute",
"id": "1T",
"value": "1T"
}
]
},
{
"__typename": "AttributeSet",
"id": "Color",
"items": [
{
"__typename": "Attribute",
"id": "Black",
"value": "#000000"
},
{
"__typename": "Attribute",
"id": "White",
"value": "#FFFFFF"
}
]
}
],
"id": "product1",
"quantity": 1,
"selectedAttributes": [
{
"value": "512G",
"type": "Capacity",
"id": "product1"
},
{
"value": "#44FF03",
"type": "Color",
"id": "product1"
}
]
}
This is my update function:
updateCartItem = (cart, product, selectedAttribute, newAttributes) => {
const existingCartItem = cart.find(
(cartItem) => cartItem.id === product.id
);
const thisCart = cart.filter((cartItem) => cartItem.id !== product.id)
if (existingCartItem) {
cart.map((cartItem) =>
cartItem.selectedAttributes.map((attr)=> attr.type===selectedAttribute.map((newAttr)=>newAttr.type
? newAttributes= [{
...attr,
value: newAttr.value,
}]
: [newAttributes = attr]
)));
return [
...thisCart,
{ ...product, selectedAttributes: newAttributes },
];
}
};
This is update state function
updateItemToCart = (product, selectedAttributes) => {
this.setState({
cartItems: this.updateCartItem(this.state.cartItems, product, selectedAttributes),
});
};
This my is my selected attributes functions
selectAttribute = (attribute, newAttribute, type, id) => {
const existingAttribute = attribute.find(
(attr) => attr.type === type && attr.id === id
);
if (existingAttribute) {
return attribute.map((attr) =>
attr.type === type && attr.id === id
? { ...attr, value: newAttribute }
: attr
);
}
return [...attribute, { value: newAttribute, type, id }];
};
selectedAttributesHandler = (newAttribute, type, id) => {
this.setState({
selectedAttributes: this.selectAttribute(
this.state.selectedAttributes,
newAttribute,
type,
id
),
});
};
What i want here is to update selectedAttributes if color or size changes but to remain the other attribute.
Example:
Color: white, Size: M
Here i change the size to L on click
Result:
Color: white, Size:L
How to update updateCartItem function to achieve this result.
You can use the spread operator
It allows you to easily populate an object or array with a shallow copy of the contect of another object or array.
The syntax is three dots followed by the name of the object or array that we want to copy.
Example:
this.setState({
...this.state,
selectedAttributes: this.selectAttribute(
this.state.selectedAttributes,
newAttribute,
type,
id
),
});
There are other ways of achieving this, but this is the likely the simplest way and is a common pattern when working with state in React.
I am trying to add data grouping by the unit name for showing functionality
const [allData , setAllData]= useState([{'unit':'' , data:[]}])
useEffect(async () => {
await axios.get(`${BACKEND_URL}/data`).then(res => {
res.data.map(elem => {
setAllData(prev =>[...prev , { 'unit': elem.unitName, 'data': [elem.lessonName] }]);
});
});
}, []);
the result is duplicating the key for the subarray which is "unit" for my exampl:
[
{
"unit": "unit 1",
"data": [
"LO1"
]
},
{
"unit": "unit 2",
"data": [
"LO2"
]
},
{
"unit": "unit 3",
"data": [
"LO3"
]
},
{
"unit": "unit 1",
"data": [
"LO15"
]
}
]
Try like that, if find unique property unit rewrite data or push new element to array
useEffect(async () => {
await axios.get(`${BACKEND_URL}/data`).then(res => {
setAllData((prev) => {
let result = [...prev];
res.data.forEach(({ unitName: unit, lessonName }) => {
const index = result.findIndex((elem) => elem.unit === unit);
if (index >= 0) {
result[index].data = [...result[index].data, lessonName]
} else {
result.push({unit, data: [lessonName]});
}
});
return result;
});
});
}, []);
In the code below, I am trying to run {this.renderCost(data,'mina')} with react js. I would like to obtain the minimum value of total using the code below, but total of an object that value of nameis Equal to for example mina(or other name because it will be changed).
I tried the following :
Firstly push the value of total using indents.push(elem.total), the expected output for this part is [2000,1000] and then get minimum value of array by Math.min(...indents),the expected output for this part is [1000] but the function doesn't work.
const data = [
{
"obj": {
"no": "1",
"info": [
{
"name": "maya"
},
{
"name": "mina"
}
],
"total":"2000"
}
},
{
"obj": {
"no": "2",
"info": [
{
"name": "maya"
}
],
"total":"1000"
}
},
{
"obj": {
"no": "3",
"info": [
{
"name": "mina"
},
{
"name": "Mike"
}
],
"total":"1000"
}
}
]
renderCost(data,name){
let indents = [];
data.map((elem) => {
this.renderTotal(elem,name,indents)
})
}
renderTotal(elem,name,indents){
for(let i = 0 ; i < elem.info.length;i++){
if (elem.info[i].name == name){
indents.push(elem.total)
}
return (
Math.min(...indents)
)
}
}
The data structure you're working with isn't ideal for this particular search however you can get to your answer with the following:
const minTotalByName = (data, name) => {
const totals = data
.filter(x =>
x.obj.info.find(y => y.name === name)
).map(x => x.obj.total);
return Math.min(...totals);
}
const min = minTotalByName(data, "mina"); // 1000
To find the min value for the name you can use below code:
const { useState } = React;
function App() {
const [name, setName] = useState("");
const filtered = data
.filter(obj => obj.obj.info.some(n => n.name === name))
.map(obj => Number(obj.obj.total));
const min = filtered.length !== 0 ? Math.min(...filtered) : "";
return (
<div>
<input onChange={(e) => setName(e.target.value)} />
<div>The result is: {min}</div>
</div>
);
}
const data = [
{
obj: {
no: "1",
info: [ { name: "maya" }, { name: "mina" } ],
total: "2000"
}
},
{
obj: {
no: "2",
info: [ { name: "maya" } ],
total: "1000"
}
},
{
obj: {
no: "3",
info: [ { name: "maya" }, { name: "Mike" } ],
total: "1000"
}
}
];
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I have an array list which needs to be converted to a single object with few of the values from array list using TypeScript in Angular 8. Below is the array:
"arrayList": [{
"name": "Testname1",
"value": "abc"
},
{
"name": "Testname2",
"value": "xyz"
}
]
This needs to be converted to the below format,
data: {
"Testname1": "abc",
"Testname2": "xyz",
}
No matter how much i try, i end up creating a list instead of a single object. Can you please help on the same?
You can use as follows,
var arr = [
{
"name": "Testname1",
"value": "abc"
},
{
"name": "Testname2",
"value": "xyz"
}
];
var result = {};
for (var i = 0; i < arr.length; i++) {
result[arr[i].name] = arr[i].value;
}
console.log(result);
Try with using .reduce() as the following:
const arrayList = [{ "name": "Testname1", "value": "abc" }, { "name": "Testname2", "value": "xyz" }];
const data = arrayList.reduce((a, {name, value}) => {
a[name] = value;
return a;
}, {});
const result = { data };
console.log(result);
Use Array.map() to get a list of [name, value] entries, then use Object.fromEntries() to convert to an object:
const arrayList = [{ "name": "Testname1", "value": "abc" }, { "name": "Testname2", "value": "xyz" }];
const result = Object.fromEntries(arrayList.map(({ name, value }) => [name, value]));
console.log(result);
Please use the below code
const rawData = {
"arrayList": [{
"name": "Testname1",
"value": "abc"
},
{
"name": "Testname2",
"value": "xyz"
}
]
};
const updatedData = {
data: {}
};
for (const item of rawData["arrayList"]) {
updatedData.data[item.name] = item.value;
}
console.log(updatedData);