How to get value of their object in react hooks array? - javascript

Good afternoon, I rarely write here. But now I really can't understand.
I am using React Select to display select. In the onChange attribute, I pass a function that forms the object and writes it to UseStat. But then I try to find an object using the find and
take an array of values from it.
const [selectedSpecificationValues, setSelectedSpecificationValues] = useState([])
const setSelectedSpecificationValuesHandler = (e, s) => {
const maybeSelectedSpecification = selectedSpecificationValues.find(
ss => ss._id === s._id
)
const objForWrite = {
_id: s._id,
name: s.name,
values: e,
}
if (maybeSelectedSpecification) {
const index = selectedSpecificationValues.indexOf(
maybeSelectedSpecification
)
let newArr = [...selectedSpecificationValues]
newArr[index] = objForWrite
setSelectedSpecificationValues(newArr)
} else {
setSelectedSpecificationValues([
...selectedSpecificationValues,
objForWrite,
])
}
}
const ssTestVal = Id => {
let result = []
if (selectedSpecificationValues.length > 0) {
const foundItem = selectedSpecificationValues.find(i => i._id === Id)
console.log(Id, foundItem)
if (foundItem) {
result = foundItem.values
}
}
return result
}
/* specifications = [
{
values: [
{
value: 0,
label: '480 min',
},
{
value: 1,
label: '120 min',
},
],
_id: '5fe74eae07905e53ebf263ec',
name: 'Duration',
slug: 'duration',
createdAt: '2020-12-26T14:54:38.362Z',
updatedAt: '2020-12-29T08:37:18.962Z',
__v: 1,
},
{
values: [
{
value: 0,
label: 'Photobook',
},
{
value: 1,
label: 'Photocard',
},
{
value: 2,
label: 'Album',
},
{
value: 3,
label: 'DVD',
},
{
value: 4,
label: 'Stickers',
},
{
value: 5,
label: 'CD',
},
],
_id: '5fe74e9107905e53ebf263eb',
name: 'Includes',
slug: 'includes',
createdAt: '2020-12-26T14:54:09.267Z',
updatedAt: '2020-12-26T16:10:16.283Z',
__v: 9,
},
] */
{
specifications &&
specifications.map((s, idx) => (
<Select
classNamePrefix='select2-selection'
options={s.values}
value={() => ssTestVal(s._id)}
onChange={e => setSelectedSpecificationValuesHandler(e, s)}
isMulti
/>
))
}
It is also important to understand that I loop a lot of selections in order to select different characteristics and their values.
I will be glad to help!
https://codesandbox.io/s/serverless-night-kez18?file=/src/App.js

Looks like minor issue with how you were computing the value for the sub-select inputs. You were defining it as though it were a callback.
<Select
classNamePrefix="select2-selection"
options={s.values}
value={() => ssTestVal(s._id)} // <-- not correct, not a callabck
onChange={(e) => setSelectedSpecificationValuesHandler(e, s)}
isMulti
/>
It should just be immediately invoked to compute and return an input's value.
<Select
classNamePrefix="select2-selection"
options={s.values}
value={ssTestVal(s._id)} // <-- invoke immediately for return value
onChange={(e) => setSelectedSpecificationValuesHandler(e, s)}
isMulti
/>

Related

.filter and .map to occur only when length is greater than 0

I'm trying to achieve the following:
For each object in addedExtra, if the field applicableOnProduct is empty, then I still want it to be rendered on the page however lets say an object that does have content in applicableOnProduct (length > 0) then it's only where I want the .filter and .map check to happen.
How do I do this in React?
const addedExtra = [{
name: 'Bed Sheet',
applicableOnProduct: [],
selected: false
},
{
name: 'Pillows',
applicableOnProduct: [],
selected: false
},
{
name: 'Luxury Bet Set',
applicableOnProduct: [{
title: 'Luxury Bed',
productId: '857493859049'
}],
selected: false
},
];
return (
{addedExtra
.filter(({ applicableOnProduct}) =>
applicableOnProduct.some(({ productId}) => productId === product.id)
)
.map((extra) => {
return <Extra {...extra}></Extra>;
})
}
)

Access the json object in react by using typescript

I have never used typescript before but in this project I need to use that. I have my api which is sending me data as shown below. Api can not be changed because it is the client's api and he is not allowing me to change that. The problem is when i access the actuals.2020-01-01 it gives me parsing error. How can I access this json object by using typescript. I need to make a login in the function that it matches all the actuals with the year and date comming in the function and return the value of the actual which matches otherwise it will return "None". I have no idea how can I do that thing. I need to deliver that to the client in 2 hours.
//Backend
actuals: {
"2020-01-01": {
value: 1,
},
"2020-02-01": {
value: 2,
},
},
//Frontend
//Table
<tbody>
{dataSeries.map(
(
data: {
name: string;
actuals: JSON;
},
index: number
) => (
<tr key={index}>
{console.log(data)}
<td>{data.name}</td>
<td>
{matchYearAndMonth(
monthBackward(0)
.currentyear,
monthBackward(0).month,
data.actuals
)}
</td>
<td>
{matchYearAndMonth(
monthBackward(1)
.currentyear,
monthBackward(1).month,
data.actuals
)}
</td>
</tr>
)
)}
</tbody>
//MatchYearAndMonth function
const matchYearAndMonth = (year: number, month: number, actuals: JSON) => {
console.log(actuals.2020-01-01);
return year;
};
type ActualsType = {[key: string]: {[key: string]: any, value: 1,}};
type DataSeriesType = {actuals: ActualsType, name: string};
function dateToStr(d=new Date()) {
const y = d.getFullYear(),
m = (d.getMonth()+1+"").padStart(2, "0"),
day = (d.getDate()+"").padStart(2, "0");
return `${y}-${m}-${day}`;
}
const today = new Date();
today.setDate(1);
const dataSeries: Array<DataSeriesType> = [
{name: "Test 1", actuals: {
"2020-01-01": {
value: 1,
},
"2020-02-01": {
value: 2,
},
"2020-09-01": {
value: 9,
},
}},
{name: "Test 2", actuals: {
"2019-09-01": {
value: 1.2,
},
"2019-10-01": {
value: 2.2,
},
}},
];
const matchYearAndMonth = (year: number, month: number, actuals: ActualsType) => {
const value = actuals[dateToStr(today)] ? actuals[dateToStr(today)]?.value : undefined;
console.log(value);
return {year, month, value};
};
dataSeries.map((v, i) => {
const parsed = matchYearAndMonth(2020, i, v.actuals);
// console.log(parsed);
})

Javascript - transforming an object of array list to new formated one?

I'm trying to transform an object contain array to another one with javascript. Below is an example of the object field and what the formatted one should look like.
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
I need The new Fields to looks like this
let newFields = {
name: 'GAME',
tags:[
{ name: 'playPES', value: "{{PES}}" },
{ name: 'playFIFA', value: "{{FIFA}}" }
]},
One contributor suggested me a method like this but i think something need to modify in it but couldn't figure it out.
export const transform = (fields) => ({
tags: Object .entries (fields) .map (([name, innerFields]) => ({
name,
tags: innerFields.map(({code, title: title: {en})=>({name: en, value: code}))
}))
});
// newFields= transform(Fields)
I'm new working with javascript so any help is greatly appreciated, Thanks.
const transform = (o) => {
return Object.entries(o).map((e)=>({
name: e[0],
tags: e[1].map((k)=>({name: (k.title)?k.title.en:undefined, value: k.code}))
}))[0]
}
console.log(transform({
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
}))
Using the entries method you posted:
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
// 1. Obtain keys and values from first object
Fields = Object.entries(oldFields);
// 2. Create new object
const newFields = {};
// 3. Create the name key value pair from new Fields array
newFields.name = Fields[0][0];
// 4. Create the tags key value pair by mapping the subarray in the new Fields array
newFields.tags = Fields[0][1].map(entry => ({ name: entry.title.en, value: entry.code }));
Object.entries(Fields) will return this:
[
"GAME",
[TagsArray]
]
And Object.entries(Fields).map will be mapping this values.
The first map, will receive only GAME, and not an array.
Change the code to something like this:
export const transform = (Fields) => {
const [name, tags] = Object.entries(Fields);
return {
name,
tags: tags.map(({ code, title }) => ({
name: title.en,
value: code
}))
}
}
Hope it help :)
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
let newFields = {
name: 'GAME',
tags:[
{ name: 'playPES', value: "{{PES}}" },
{ name: 'playFIFA', value: "{{FIFA}}" }
]
}
let answer = {
name: "Game",
tags: [
]
}
Fields.GAME.map(i => {
var JSON = {
"name": i.title.en,
"value": i.code
}
answer.tags.push(JSON);
});
console.log(answer);
I think that this is more readable, but not easier... If you want the result as object you need to use reduce, because when you do this
Object.keys(Fields)
Your object transform to array, but reduce can change array to object back.
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
const result = Object.keys(Fields).reduce((acc, rec) => {
return {
name: rec,
tags: Fields[rec].map(el => {
return {
name: el.title.en,
value: el.code
}
})
}
}, {})
console.log(result)
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
const transform = (fields) => ({
tags: Object .entries (fields) .map (([name, innerFields]) => ({
name,
tags: innerFields.map(({code, title: title,en})=>({name: title.en, value: code}))
}))
});
//check required output in console
console.log(transform(Fields));

Taking JSON values in a response and mapping them to a state object with keys?

[Noob to Javascript and React] I am using an API that returns an object with values like this. AAPL, AMZN, FB, GOOGL, can be anything based on the function's string array input.
{
AAPL: { price: 329.99 },
AMZN: { price: 2563.05 },
FB: { price: 239.93 },
GOOGL: { price: 1469.12 }
}
How could I consider dynamically mapping a response like this into a state object like this? The id property doesn't exist, it needs to be created.
state = {
stocks: [ { id: 1, name: 'AAPL', price: 329.99 }, { id: 2, name: 'AMZN', price: 2563.05 }, ...]
}
I'm able to successfully print the stock names and their prices separately but I am having trouble figuring out how I could wire them into a state object like what's above.
function getCurrentPriceOfBatchStocks(_stocks) {
iex
.symbols(_stocks)
.price()
.then(res => {
console.log(typeof res);
console.log(res);
console.log(Object.keys(res));
console.log(Object.values(res));
});
}
Not sure where you're getting id from, so I'm using idx as an example.
const stocks = Object.keys(resp).map((key, idx) => ({ id: idx + 1, name: key, price: resp[key] }))
Here is an implementation. With Object.entries, you get an array with an array of [key, value] of your original object. And you can map this array to a different format.
You can check the result with the Run code snippet button.
let st = {
AAPL: { price: 329.99 },
AMZN: { price: 2563.05 },
FB: { price: 239.93 },
GOOGL: { price: 1469.12 }
}
let stocks = Object.entries(st).map(([key, value], index) => ({id: index + 1, name: key, price: value.price}))
console.log(stocks)
const res={
AAPL: { price: 329.99 },
AMZN: { price: 2563.05 },
FB: { price: 239.93 },
GOOGL: { price: 1469.12 }
}
console.log(Object.entries(res).map((entry,index)=>{
return {
id:index+1,
name:entry[0],
...entry[1]
}
}));

Merge the object using typescript

In my angular application i am having the data as follows,
forEachArrayOne = [
{ id: 1, name: "userOne" },
{ id: 2, name: "userTwo" },
{ id: 3, name: "userThree" }
]
forEachArrayTwo = [
{ id: 1, name: "userFour" },
{ id: 2, name: "userFive" },
{ id: 3, name: "userSix" }
]
newObj: any = {};
ngOnInit() {
this.forEachArrayOne.forEach(element => {
this.newObj = { titleOne: "objectOne", dataOne: this.forEachArrayOne };
})
this.forEachArrayTwo.forEach(element => {
this.newObj = { titleTwo: "objectTwo", dataTwo: this.forEachArrayTwo };
})
console.log({ ...this.newObj, ...this.newObj });
}
In my real application, the above is the structure so kindly help me to achieve the expected result in the same way..
The working demo https://stackblitz.com/edit/angular-gyched which has the above structure.
Here console.log(this.newObj) gives the last object,
titleTwo: "ObjectTwo",
dataTwo:
[
{ id: 1, name: "userFour" },
{ id: 2, name: "userFive" },
{ id: 3, name: "userSix" }
]
but i want to combine both and need the result exactly like the below..
{
titleOne: "objectOne",
dataOne:
[
{ id: 1, name: "userOne" },
{ id: 2, name: "userTwo" },
{ id: 3, name: "userThree" }
],
titleTwo: "ObjectTwo",
dataTwo:
[
{ id: 1, name: "userFour" },
{ id: 2, name: "userFive" },
{ id: 3, name: "userSix" }
]
}
Kindly help me to achieve the above result.. If i am wrong in anywhere kindly correct with the working example please..
You're assigning both values to this.newObj, so it just overwrites the first object.
Also, there is no need for your loop. It doesn't add anything.
Instead, you can do:
this.newObjA = { titleOne: "objectOne", dataOne: this.forEachArrayOne };
this.newObjB = { titleTwo: "objectTwo", dataTwo: this.forEachArrayTwo };
console.log({ ...this.newObjA, ...this.newObjB });
**
EDIT **
Having spoken to you regarding your requirements, I can see a different solution.
Before calling componentData, you need to make sure you have the full data. To do this, we can use forkJoin to join the benchmark requests, and the project requests into one Observable. We can then subscribe to that Observable to get the results for both.
The code would look something like this:
createComponent() {
let benchmarks, projects;
let form = this.productBenchMarkingForm[0];
if (form.benchmarking && form.project) {
benchmarks = form.benchmarking.filter(x => x.optionsUrl)
.map(element => this.getOptions(element));
projects = form.project.filter(x => x.optionsUrl)
.map(element => this.getOptions(element));
forkJoin(
forkJoin(benchmarks), // Join all the benchmark requests into 1 Observable
forkJoin(projects) // Join all the project requests into 1 Observable
).subscribe(res => {
this.componentData({ component: NgiProductComponent, inputs: { config: AppConfig, injectData: { action: "add", titleProject: "project", dataProject: this.productBenchMarkingForm[0] } } });
})
}
}
getOptions(element) {
return this.appService.getRest(element.optionsUrl).pipe(
map((res: any) => {
this.dataForOptions = res.data;
element.options = res.data;
return element;
})
)
}
Here is an example in Stackblitz that logs the data to the console

Categories

Resources