Change input in a Child React component - javascript

hello i have a component in react that has this usetstate
const [answers, setAnswers] = useState({
q1: '',
q2: '',
q4: '',
q5: '',
});
and i have an array of question :
{id: q1
q: "question1"
att: []
}
{id: q2
q: "question2"
att: []
}
{id: q3
q : "question3"
att: []
}
{id: q4
q: "question4"
att: []
}
{id: q5
q: "question5"
att: []
}
]
and i want in the parnt component to send each qestion to the child compont
return(questions.map((obj)=><childComponent obj = {obj}/>));
the problem is the if i set a input elemnt in the child component i can only put one char
and i think its because it render the parent elment each time
i try to set the value of the input with
props.setAnswers(...answerts , [id]:event.target.value)
but its not working
can someone can help me and give me a way to do it so i can do it and still save the values in the parent component?
thanks

Related

Update content of array and remove duplicates in REACT JS

Good day,
I have a following problem.
I have two arrays. One of them is storing items that comes from API and it goes like this:
0: {id: '80682ddb-0785-ec11-94f7-281878bb3ca6', name: 'test', typeId: 14, typeName: 'typename', typeAbbreviation: 'asa'}
1: {id: '80682ddb-0785-ec11-94f7-212113ca6', name: 'number 2', typeId: 14, typeName: 'typename', typeAbbreviation: 'asa'}
2: {id: '80682ddb-0785-ec11-94f7-24124878bb3ca6', name: 'number 3', typeId: 14, typeName: 'typename', typeAbbreviation: 'asa'}
Values from this array are used to list checkboxes.
Second array is updated every time user clicks one of the checkboxes. This checkbox is being puhsed to the table with additional checked property:
0: {checked: true, id: '80682ddb-0785-ec11-94f7-281878bb3ca6', name: 'test', typeId: 14, typeName: 'typename', typeAbbreviation: 'asa'}
My goal is to push the values to the table - fill it with all checkboxes and then replace the certain checkbox with the selected one.
In general values from Api are replaced with certain selected checkboxes values with addional checked prop.
I tried to achieve it in a few ways using mapping, filtering and so on like that:
var newArray = [];
selectedItems?.forEach(function(mainObject) {
for (let i=0; i<currentItems.length; i++){
if(currentItems[i].id === mainObject.id){
newArray.push(mainObject);
} else {
newArray.push(currentItems[i])
}
}
});
I would appreciate Your help. Any ideas how to achieve it?
What I understood is that you have a list that comes from an API, and you want to display it as checkboxes, and only get the ones that the user selects.
you can use map.
I think your approach is right, you should create new array, instead of trying to delete items from the original array.
const selectedItems = [];
const onChange = (e)=>{
let id = e.target.value;
if(e.target.checked){// if check box is selected
arrayFromApi.map(item => {
if(item.id === id){
selectedItems.push(item);
}
});
}else{// if checkbox is deselected
selectedItems.filter(item => item.id === id);
}
}

How to filter multiple properties of one array of object from the other array of object?

I am trying to solve the problem in which i have to apply multiple filters to the array of object. Let suppose I am having a larger array of object which contains the configuration property which is further an object. On other side i have small object which are the ones the user chooses to filter(based on the checkboxes). i want to compare objects made with the parent array of objects by selecting multiple values.
So in the image the user chooses multiple values(using check boxes) and based on that he needs to filter the main array of objects.So after checking the checkboxes i get childObject and i have to filter parentArray on the basis of that..... please help me with this:
childobject =
{'Bathroom': '[2,1]',
'Bedroom': '[3,2]',
'halfBathroom':'0',
'name':'[2BD-2BA,2BD-2BA-1]'}
parentArray = [
0:{},
1:{},
2:{
'property1':'____',
'property2':'_____',
'configuration':'{
bathroom: 2
bedroom: 2
created_at: "2019-03-08 20:52:52"
created_by: 264
half_bathroom: 1
id: 26
is_selected: 0
name: "2BD-2BA-1/2BA"
name_en: "2BD-2BA-1/2BA"
name_es: "2RE-2BA-1/2BA"
status: 1
updated_at: "2019-08-23 05:39:44"
}'
}
3: {},
4:{}
]
I had to update the datastructure at some points:
You had different key in child and parent (upper/lowercase + camelcase/_ writing)
Some Missing } in the parent.
In child quotationmarks for integer deleted.Missing , added.
Changing some values in cruiteria, so that there is a result.
In parent delting of 0:, 1:, 2:, 3:, 4: to get a valid array.
childArray = {
'bathroom': [2,1],
'bedroom': [3,2],
'half_bathroom':1,
'name':['2BD-2BA', '2BD-2BA-1/2BA']
};
parentArray = [
{},
{},
{
'property1':'____',
'property2':'_____',
'configuration':{
bathroom: 2,
bedroom: 2,
created_at: "2019-03-08 20:52:52",
created_by: 264,
half_bathroom: 1,
id: 26,
is_selected: 0,
name: "2BD-2BA-1/2BA",
name_en: "2BD-2BA-1/2BA",
name_es: "2RE-2BA-1/2BA",
status: 1,
updated_at: "2019-08-23 05:39:44"
},
},
{},
{}
]
let res = parentArray.filter(elem => Object.entries(childArray).every(([key,val]) => {
let conf = elem.configuration;
if (conf===undefined) return false;
if (typeof(val) === 'object') {
return val.some(crit => crit===conf[key]);
} else {
return val===conf[key];
}
}));
console.log(res);

Compare between two arrays

While I was thinking in someway to compare between two arrays, accidentally for the first time something like this happens with me.. something worked with me for the first time without showing me any errors!
This is a very simplified visualization for an application I'm working on currently.
I have two arrays, one called options, the other is called correct.
so the options are options of some question, the chances are the chances of this question.
in this example two of the options are correct answers..
so what I have to do is to compare between this two arrays to check if it returns true (later) or if it's returning false (not included in the code).
could you please explain for me how this actually worked?
const options = ['facebook', 'twitter', 'tango', 'skype'];
const correct = ['twitter', 'skype'];
const trueIndexes = [];
options.forEach((cur, index) => {
correct.forEach((cur1, index1) => {
if (cur === cur1) {
trueIndexes.push(index);
}
});
});
console.log(trueIndexes);
There are nested forEach loops for each array, and during each inner loop there is a conditional test to ascertain if one element exists in the other. If so, the index of where the matching item exists in the other array is pushed to the new trueIndexes array.
Another way to write this is:
const options = ['facebook', 'twitter', 'tango', 'skype']
const correct = ['twitter', 'skype']
const trueIndices = correct.reduce((_trueIndices, correctItem) => {
let correctItemIndex = options.indexOf(correctItem)
if(correctItemIndex !== -1) _trueIndices.push(correctItemIndex)
return _trueIndices
}, [])
console.log(trueIndices)
or
const options = ['facebook', 'twitter', 'tango', 'skype']
const correct = ['twitter', 'skype']
const trueIndices = []
correct.forEach((correctItem) => {
let correctItemIndex = options.indexOf(correctItem)
if(correctItem !== -1) trueIndices.push(correctItem)
})
console.log(trueIndices)
Both of these alternate solutions should be faster.
Your code goes through each option and compares it to both correct values.
If they match the index of the option is added to the true indexes list.
So the comparisons are like follows:
'facebook' = 'twitter'? no
'facebook' = 'skype'? no
'twitter' = 'twitter'? YES -> add index to list
'twitter' = 'skype'? no
'tango' = 'twitter'? no
'tango' = 'skype'? no
'skype' = 'twitter'? no
'skype' = 'skype'? YES -> add index to list
As explained by others, you just iterate over all the combinations of these 2 arrays and collect the indexes where an option is in both arrays(in other words, if an option is true)
I just wanted to add that you should perhaps change your data structure so that options are stored with the questions...and correct answers are indicated by a flag so they don't need to be looked up.
For example:
const questions = [
{
id: 'social_1',
question: 'Which of these are popular social media sites?',
answers: [
{id: 'fb', label: 'Facebook', correct: true},
{id: 'skype', label: 'Skype', correct: false},
{id: 'twitter', label: 'Twitter', correct: true},
{id: 'yt', label: 'YouTube', correct: false},
]
}, {
id: 'cars_1',
question: 'Which of these are car brands?',
answers: [
{id: 'tesla', label: 'Tesla', correct: true},
{id: 'bmw', label: 'BMW', correct: true},
{id: 'twitter', label: 'Twitter', correct: false},
{id: 'yt', label: 'YouTube', correct: false},
]
}
];
https://jsfiddle.net/rainerpl/L438qjms/26/

Javascript method and local variable

I have been searching through the internet and cannot find the right word to search so I end up here asking again to all of you seniors in Javascript.
The code below is taken from the answer on these question
I really don't understand how the method or function work.
var list = [{id: 1,title: 'home',parent: null},{id: 2,title: 'about',parent: null},{id: 3,title: 'team',parent: 2},{id: 4,title: 'company',parent: 2} ];
function treeify(list) {
var treeList = [];
var lookup = {};
list.forEach(function(obj) {
obj['children'] = [];
lookup[obj['id']] = obj;
});
console.log(lookup); // [problem number 1]
list.forEach(function(obj) {
if (obj['parent'] != null) {
lookup[obj['parent']]['children'].push(obj);
} else {
treeList.push(obj);
}
});
console.log(treeList); // [problem number 2]
};
treeify(list);
On problem number 1:
It resulted an object that had already a children on each parent which is supposedly I think that, parent should have an empty array children at that moment. How does it work? Please enlightened me.
On problem number 2
treeList already formed the hierarchy tree. How it happen? it didn't even push the lookup variable to the treeList variable? It only pushes the obj with a parent that is equal to null (which is the root parent).
Hoping for your answer.
If you know any blog, article and etc. that may help me understand javascript please don't hesitate to add the link in your answer.
Many Thank you!
var list = [
{id: 1,title: 'home',parent: null},
{id: 2,title: 'about',parent: null},
{id: 3,title: 'team',parent: 2},
{id: 4,title: 'company',parent: 2}
];
treeify(list);
function treeify(list) {
var treeList = []; //local array
var lookup = {}; //local object
// iterate over each element in list array
list.forEach(function(obj) {
// add a children property to each element in the array
// in this case the children property is an array
obj['children'] = [];
// obj['id'] returns 1,2,3,4
// lookup is an object so we use the id of each element in the list array as a key
// first iteration adds key : 1 and value {id:1, title: 'home', parent: null, children: [] }
// second iteration adds key : 2 and value {id:2, title: 'about', parent: null, children: [] }
// ...
lookup[obj['id']] = obj;
});
/*
console.log(lookup) should output
{
1: {id: 1,title: 'home', parent: null, children: []},
2: {id: 2,title: 'about', parent: null, children: []},
3: {id: 3,title: 'team', parent: 2, children: []},
4: {id: 4,title: 'company', parent: 2, children: []}
}
however, if you run the code the lookup object gets modifyed in
the lines below (lookup[obj['parent']]['children'].push(obj);),
therefore, some items in the lookup object will have children elements in its child array
*/
console.log(lookup); // [problem number 1]
list.forEach(function(obj) {
if (obj['parent'] != null) {
// this line modifyes the lookup object at runtime
// obj has a parent, so we add it to the corresponding parents children array using the id
lookup[obj['parent']]['children'].push(obj);
} else {
//only adds an element to the treelist array if its a parent element
treeList.push(obj);
}
});
console.log(treeList);
};
Problem 1:
You are right with your assumption, but the problem is that console.log is logging a reference. Because the lookup object gets changed later on you see these changes. read more
function treeify(list) {
var treeList = [];
var lookup = {};
list.forEach(function(obj) {
obj['children'] = [];
lookup[obj['id']] = obj;
});
console.log(lookup); // Now you're right
};
Problem 2:
All objects in lookup are referenced to list.
lookup[obj['id']] = obj;
Here the childrens get changed.
lookup[obj['parent']]['children'].push(obj);
In treeList are also the same references.

Immutable.js mergeDeepWith issue

I amusing Immutable.js and having problems merging an object with an array .
My fucntion for merging is:
function singleTrackReducer(state = Immutable.Map(singleTrack), action) {
switch (action.type){
case AudioFormActions.CHANGE:
return state.mergeDeepWith((prev, next) => next, action.entity);
default:
return state;
}
}
The object that I am merging to looks like this:
const singleTrack = {
songTitle: '',
mainArtists: [],
featuredArtists: [],
releaseDate: '',
primaryGenre: '',
isExplicit: false,
labelName:'',
upCode: '',
eanCode: '',
isrcCode:'',
copyRight: ''
};
I am trying to update the mainArtists property.. For example i can add several artists to my artist array and perform an update successfully. However when I delete an object from the array it appears to be filled with a previous object.
Say for example the artist Array is [drake, rihanna, tyga]
If I call the function with action entity [drake, rihanna, tyga, john] it updates fine and the mainArtists property becomes [drake, rihanna, tyga, john].
when I delete an artist example tyga and the array is [drake, rihanna, john]
the mainArtist property becomes [drake, rihanna, john, john]
Can anyone explain how I can resolve this issue
I think this code will help you understand the issue:
var Immutable = require('immutable');
console.log(
Immutable.List(['a', 'b', 'c'])
.mergeDeep(['a', 'c'])
);
// output: List [ "a", "c", "c" ]
console.log(Immutable.List(['a', 'b', 'c'])
.mergeDeepWith((prev, next) => {
console.log(`Conflict between ${prev} and ${next}.`);
return next;
}, ['a', 'c'])
);
// output: Conflict between a and a.
// Conflict between b and c.
// List [ "a", "c", "c" ]
Basically, when merging lists, items appear to be copied from one to the other at each index, and if there's already a value at that index, it's considered a conflict:
For index #0, there's "a" in the first list and "a" in the second list. We resolve the conflict by preferring the second value (though in this case they're identical). So index #0 gets "a".
Then we go to index #1 and find the first list has "b" and the second list has "c". We resolve the conflict by choosing the second value, so index #1 gets "c".
Now for index #2, we have no conflict, since only the first list has a value. We keep "c" in index #2, so the final list is "a", "c", "c".
You could instead use a set, but that basically performs a union operation, so nothing would ever be deleted:
console.log(
Immutable.Set(['a', 'b', 'c'])
.mergeDeep(['a', 'c'])
);
// output: Set { "a", "b", "c" }
I don't actually think you're looking to do a merge of this list at all... I think you simply want to copy the new value over the old value. If that's the case, maybe you're just looking for merge instead of mergeDeep:
var state = Immutable.Map({
songTitle: '',
mainArtists: [],
featuredArtists: [],
releaseDate: '',
primaryGenre: '',
isExplicit: false,
labelName:'',
upCode: '',
eanCode: '',
isrcCode:'',
copyRight: ''
});
function doMerge(state, newState) {
// no deep merge here, just copy whatever fields are present in newState
return state.merge(newState);
}
console.log(state.get('mainArtists'));
// output: []
state = doMerge(state, {
mainArtists: ['drake', 'rihanna', 'tyga']
});
console.log(state.get('mainArtists'));
// output: List [ "drake", "rihanna", "tyga" ]
state = doMerge(state, {
mainArtists: ['drake', 'rihanna', 'tyga', 'john']
});
console.log(state.get('mainArtists'));
// output: List [ "drake", "rihanna", "tyga", "john" ]
state = doMerge(state, {
mainArtists: ['drake', 'rihanna', 'john']
});
console.log(state.get('mainArtists'));
// output: List [ "drake", "rihanna", "john" ]

Categories