React store data from a state into another state - reactjs

can anyone please help me solve this problem, I am trying to get some attribute from the tempList state to store into listReceiver state by using gosetListReceiver() function below.
const [tempList, setTempList] = useState([]);
const [listReceiver, setListReceiver] = useState([]);
function gosetListReceiver() {
let i = 0;
while (i < tempList.length) {
setListReceiver([
...listReceiver,
{
name: tempList[i]["name"],
phone: tempList[i]["receiver"]
}
]);
i++;
}
}
but when I am mapping/console the listReceiver state after that , I expect that it will store 3 array from the tempList into listReceiver but it only have the last item from tempList that stored into it. how can i fix this?
below the sample data of tempList as i need to take name and receiver attribute to store into listReceiver

Every time through the loop, you are overwriting the state and thus wiping out anything you did on the last time through the loop. To fix this, you have two options.
Use the function version of set state so that you always get passed in the most recent version of the state:
setListReceiver((prev) => [
...prev,
{
name: tempList[i]["name"],
phone: tempList[i]["receiver"],
},
]);
Wait until you've created the full array, and then set state just once at the end:
function gosetListReceiver() {
let i = 0;
const newState = [...listReceiver];
while (i < tempList.length) {
newState.push({
name: tempList[i]["name"],
phone: tempList[i]["receiver"],
});
i++;
}
setListReceiver(newState);
}
P.S, this code looks like it would be better as a for loop, instead of a while loop:
const newState = [...listReceiver];
for (let i = 0; i < tempList.length; i++) {
newState.push({
name: tempList[i]["name"],
phone: tempList[i]["receiver"],
});
}
setListReceiver(newState);

I didn't tested, but the array brackets [] at the beginning of setListReceiver() looks suspicious to me.
Try without them:
...
setListReceiver(
...listReceiver,
{
name: tempList[i]["name"],
phone: tempList[i]["receiver"]
}
);
...
Or a way which should definitelly work, have a look at Array.push(...).

Related

Binding data to treeview nodes from array issue in react

I have follow below example to create tree view with check boxes. Its working fine.
https://github.com/jakezatecky/react-checkbox-tree
Now I am trying to add data from my post method. I have fill data to array. But I tried to add it to loop for get data.
const persons = [];
for (let i = 0; i < data.length; i++) {
persons = [{ value: data[i].id, label: data[i].name }];
}
this.setState({ persons });
Checkbox code
render() {
return (
<CheckboxTree
nodes={this.state.persons}
iconsClass="fa5"
checked={this.state.checked}
expanded={this.state.expanded}
onExpand={expanded => this.setState({ expanded })}
/>
);
}
I am getting only last record in this treeview. but loop is working correctly Please give some suggestions to solve this. thank you
You are getting the last object only because you are re-initialing the person array each time.
Instead you have to push that object to the array.
Try like this:
const persons = [];
for (let i = 0; i < data.length; i++) {
persons.push({ value: data[i].id, label: data[i].name })
}
this.setState({ persons });

CanJS - Incorrect list objects type after mapping

If I have this instantiation const someObj = new MyObj({...someParams}) and MyObj is defined this way:
MyObj = DefineMap.extend("MyObj", {
myProp: {
Type: AnotherType.List
}
})
and
AnotherType.List = CanList.extend("AnotherType.List", {
Map: AnotherType
}, {
serialize() {
const res = [];
for (let i = 0; i < this.attr("length"); i++) {
res.push(this.attr(i.toString()).serialize());
}
return res;
}
})
then the someObj.myProp[0] type is DefineMap instead of AnotherType. How can I fix this?
I already tried this but still not working: const someObj = canReflect.assignDeep(new MyObj(), {...someParams})
With the help of Bitovi community I solved it (thanks to Brad Momberger).
So Brad explained that it happens because of the DefineList's bubble binding and the same doesn't happen with DefineMap objects.
So we always need to serialize the lists first the get the correct type of the list entries at the end, like this:
const someObj = new MyObj({
...someParams,
myProp: someParams.myProp.serialize()
})
You can see the full explanation here.

Dynamic # of states using for loop and setState . Then need to use states after all have been set

Dynamic number of states. The number of states are dynamic and depends on this mppt number which depends on the user input. I create the states and then after they are all created in the for loop... I'd like to do something with it. I would normally do it in the callback, but I'm using a for loop to create the dynamic number of states. This sets up the defaults and number of elements depending on mppt number. Afterwards, it will be updated by an onChange.
const defaultValues = {
1:{
isc: 10.88,
power: 3834.5999999999995,
vmp: 497,
voc: 584.3312579999999,
se: 14,
st: 1,
},
2: {isc: 9.00,
power: 3834.5999999999995,
vmp: 600,
voc: 584.3312579999999,
se: 12,
st: 1},
}
const mppt = 2
.
.
.
componentDidMount(){
console.log('Sizing Mounted?')
for(let i=1 ; i <= mppt ; i++){
console.log(i)
this.setState({ [`${i}`] : defaultValues[i]}, ()=>{
console.log('state been set?')
console.log(this.state[`${i}`]) //this works
})
}
console.log('Check if state has been checked by here to feed into next function')
console.log(this.state[`1`]) // undefined
//This function uses the new set states
this.createElementDefaults() //uses undefined state values
}
The asyncronous nature of setStates is messing with this. Any suggestions?
Try building the object first, set it into the state and then use your funciton in the callback:
componentDidMount() {
let s = {};
for (let i = 1; i <= mppt; i++) {
s[`${i}`] = defaultValues[i];
}
this.setState((prevState) => ({ ...s }), () => {
console.log(this.state);
this.createElementDefaults()
});
}

How to use this.state.rent value instead of this.props.house.rent value in cache.readQuery or cache.writeQuery

The old value comes back into the input field.
I had initialized this.props.house.rent (which is the old value coming back) with input field value this.state.rent (user entered value) but I cannot do it as it becomes antipattern syntax, you can see it in below comments of code.
cacheUpdate = (cache, { data: { updateHouse } }) => {
const data = cache.readQuery({
query: QUERY_CONFIRM_QUERY,
variables: { id: this.props.confirmId },
});
const houses = data.queryConfirm.houses;
const prevHouse = this.props.house;
//prevHouse.rent = this.state.rent; // this.state.rent is user entered input value
const updatedHouses = houses.map(house => {
if (house.id === prevHouse.id) {
const updatedHouseItem = _.pickBy(updateHouse, _.identity);
return { ...prevHouse, ...updatedHouseItem };
}
return house;
});
data.queryConfirm.houses = updatedHouses;
cache.writeQuery({
query: QUERY_CONFIRM_QUERY,
variables: {
id: this.props.confirmId,
},
data,
});
};
I want the old value to be removed from readQuery or writeQuery of cache.
Hope this helps someone. Ooof..I think a lot, it was simple actually. I thought to make callback, but not possible as values are coming from database. Anyways, in conclusion simple look at the value of data.queryConfirm.houses in the console and assign the required array like, say I required was data.queryContact.houses[0].rent and initialize it to this.state.rent. That's all.

excluding from an object angular ng-change

Hello guys i am trying to clear my ng-model when i fire my change function but my problem that i don't want to delete all i want to exclude one item in the object.
function change() {
if (vm.location.type) {
angular.forEach(vm.location, function (value, index) {
delete vm.location;
});
}
}
so i don't want to delete the
vm.location.type
my
vm.location
has
vm.location.boundaries;
vm.location.region;
vm.location.address;
vm.location.name;
vm.location.nonVisitingRadius;
vm.location.visitingRadius;
See the code below,
var obj = { a:123, b:123, c:123 }
delete obj.a;
Hence obj will be like this {b:123, c:123}
Note: Dont need any for loop to delete property from object
Updated Answer:
var obj= {
a: 'aaa',
b: 'bbb',
c: 'ccc',
d: 'ddd'
};
var removeObj = function(obj, props) {
for(var i = 0; i < props.length; i++) {
if(obj.hasOwnProperty(props[i])) {
delete obj[props[i]];
}
}
};
removeObj (obj, ["a", "d"]);
i don't know if i understand correctly what you're asking, but if you want to clear all the fields of your object preserving only type and preserving the reference of the object with plain javascirpt (no libraries), loop over the fields and check if the i field is equal to type.
for(var i in model.location){
if(i !== 'type')
delete model[i];
}
with underscore.js you could define a default model like:
var defaultModel = {
location: {
region: '',
address: '',
name: '',
nonVisitingRadius: '',
visitingRadius: '',
type: 'defaultvalue'
}
}
and when ng-change is triggered inside the function
_.extend(model, defaultModel);
that will keep the default value for type and clear all the others.
You can do it this with a temporary object :
let tempLocation = {};
tempLocation.type = $scope.location.type;
$scope.location = tempLocation;

Resources