the value does not change when the state is changed - reactjs

when the search value is changed, the state does not change, although when the search value is reduced, the changes occur instantly
this is one code in order*
if(prop.props.statePokemon){
prop.props.setStatePokemon(false)
why the given value does not change:
setPokemon(saveDataPokemon) // the value does not change
but all other logs are going fine:
let rangePokemonFromAttack:(IPokemon | undefined | any)[] = allPokemon.data.map((pokemon: IPokemon) => {
if(prop.props.rangeAttack.rangeAttackFrom <= pokemon.stats[1].base_stat && pokemon.stats[1].base_stat <= prop.props.rangeAttack.rangeAttackTo){
return pokemon
}
}).filter((pokemon: IPokemon | undefined) => {
return pokemon !== undefined
})
console.log(allPokemon,'all',
saveDataPokemon, 'save',
rangePokemonFromAttack ,'range')
if(typeof rangePokemonFromAttack[0] !== 'undefined'){
setPokemon(saveDataPokemon)
setPokemon({data: rangePokemonFromAttack})
}else{
setPokemon(saveDataPokemon)
}
}
prop.props.rangeAttack.rangeAttackFrom = 0
prop.props.rangeAttack.rangeAttackTo = 400
}

The state variables doesn't change like that you need to use setState() function for this purpose, which in turn calls the render again. For more info Google setState or visit this link https://reactjs.org/docs/react-component.html In this docs search setState function

I made a mistake and caused another state
prop.props.setStatePokemon(false)
let rangePokemonFromAttack:IPokemon[] = saveDataPokemon.data.filter((pokemon: IPokemon) => {
if(prop.props.rangeAttack.rangeAttackFrom <= pokemon.stats[1].base_stat
&& pokemon.stats[1].base_stat
<= prop.props.rangeAttack.rangeAttackTo){
return pokemon
}
})
if(typeof rangePokemonFromAttack[0] !== 'undefined'){
setPokemon({data: rangePokemonFromAttack})
}else{
setPokemon(saveDataPokemon)
}

Related

Arraylist doesn't get refilled and/or filtered

I have a list in angular, an array. OnInit it gets filled from the right corresponding database items. I created a form above it. When you enter something in the form, it acts like a filter. This works, the first time. When you erase something from the form and enter something else, the list should be refreshed and afterwards filtered based on the new input. This doesn't happen. I put the formula that happens on onInit in my function to refill the list.
Below you can find my function (I left the console logs in) and a screenshot of the problem. First I look for a user (joeri.boons#hi10.be) which returns three results. Than I erase the user and look based on a month 7. The screen returns a new unfilterd list while in the console it still holds the list of 3 x user joeri.boons#hi10.be. So there is an inconsistency to. If you look at screen result you would think of a filter problem, the console points at a refreshproblem.
if more code is required let me know.
updateWithFilter(): void {
console.log("function update filter reached")
console.log(this.listadapted);
if(this.listadapted == true){
// this.timesheetsHandled = {} as TimeSheet[];
this.getHandledSheet();
console.log("getHandledSheet executed")
}
if(this.filterUsername.trim() && !this.filterYear && !this.filterMonth){
console.log("option 1 reached")
console.log(this.filterUsername.trim());
console.log(this.filterYear);
console.log(this.filterMonth);
this.timesheetsHandled = this.timesheetsHandled.filter(sheet => sheet.username == this.filterUsername);
this.listadapted = true;
} else if(!this.filterUsername.trim() && !this.filterYear && this.filterMonth){
console.log("option 2 reached");
console.log(this.filterUsername.trim());
console.log(this.filterYear);
console.log(this.filterMonth);
console.log("before filter");
this.timesheetsHandled.forEach(sheet => console.log(sheet.username));
this.timesheetsHandled = this.timesheetsHandled.filter(sheet => sheet.month == this.filterMonth);
console.log("after filter");
this.timesheetsHandled.forEach(sheet => console.log(sheet.username));
// console.log(this.timesheetsHandled.filter(sheet => sheet.month == this.filterMonth));
this.listadapted = true;
} else if .. more options
}
ngOnInit(): void {
this.getHandledSheet();
}
getHandledSheet(): void {
this.timesheetService.getAllTimesheets().subscribe({next: (response: TimeSheet[]) => {this.timesheetsHandled = response.filter(sheet => sheet.status == 'HANDLED') }}) ;
}
My guess would be that this is caused by loading data in ngOnInit. As the documentation (https://angular.io/api/core/OnInit) states : [...] It is invoked only once when the directive is instantiated.
I suspect that you create one instance and re-use it and the ngOnInit method does not get called again.
UPDATE:
The issue is that the call to this.getHandledSheet(); does a call to .. .subscribe({next: .. which is delayed and the rest of the function is executed first.
So the actual code after next: is only executed after the timeSheetService is done loading the data.
So either you apply the filter in the
{next: (response: TimeSheet[]) => {this.timesheetsHandled = response.filter(sheet => sheet.status == 'HANDLED') }}
block after filtering for 'HANDLED' or you'll try to await in the update function.
Create two variables, one that will always remain unfiltered, then another that will be filtered.
The problem will be that the original list is filtered, hence you are losing the original data after filtering!
timesheetHandled: TimeSheet[];
timesheetHandledOriginal: TimeSheet[];
updateWithFilter(): void {
console.log('function update filter reached');
console.log(this.listadapted);
if (this.listadapted == true) {
// this.timesheetsHandled = {} as TimeSheet[];
this.getHandledSheet();
console.log('getHandledSheet executed');
}
if (this.filterUsername.trim() && !this.filterYear && !this.filterMonth) {
console.log('option 1 reached');
console.log(this.filterUsername.trim());
console.log(this.filterYear);
console.log(this.filterMonth);
this.timesheetsHandled = this.timesheetHandledOriginal.filter(
sheet => sheet.username == this.filterUsername
);
this.listadapted = true;
} else if (!this.filterUsername.trim() && !this.filterYear && this.filterMonth) {
console.log('option 2 reached');
console.log(this.filterUsername.trim());
console.log(this.filterYear);
console.log(this.filterMonth);
console.log('before filter');
this.timesheetsHandled.forEach(sheet => console.log(sheet.username));
this.timesheetsHandled = this.timesheetHandledOriginal.filter(
sheet => sheet.month == this.filterMonth
);
console.log('after filter');
this.timesheetsHandled.forEach(sheet => console.log(sheet.username));
// console.log(this.timesheetsHandled.filter(sheet => sheet.month == this.filterMonth));
this.listadapted = true;
}
// else if .. more options
}
ngOnInit(): void {
this.getHandledSheet();
}
getHandledSheet(): void {
this.timesheetService.getAllTimesheets().subscribe({
next: (response: TimeSheet[]) => {
this.timesheetsHandled = response.filter(sheet => sheet.status == 'HANDLED');
this.timesheetHandledOriginal = JSON.parse(JSON.stringify(this.timesheetsHandled));
},
});
}

output-task.js:171 Uncaught TypeError: Cannot assign to read only property 'multiDrag' of object '#<Object>'

I am getting this error when I am trying to update my state using props basically when my condition matches the flag would certainly go back to its initial state value but it is showing error in this case.
var finalVal;
if (
typeof bigFinalValue === "undefined" ||
bigFinalValue.length < 1 ||
this.props.singleDrag === true
) {
console.log("here he is", this.props.singleDrag);
finalVal = <Content>{task.word}</Content>;
this.props.multiDrag = false;
}
if (
(typeof bigFinalValue === "undefined" || bigFinalValue.length > 1) &&
this.props.multiDrag === true
) {
console.log("bigFinalValue", bigFinalValue);
console.log("selectionCount", selectionCount);
console.log("and here he is again...");
finalVal = <Content>{bigFinalValue}</Content>;
this.props.multiDrag = false;
}
Here the error is pretty obvious. You are trying to set props to false.
this.props.multiDrag = false; //wrong
Props are READ ONLY. You can read the article below to get a better understanding how it works.
https://itnext.io/what-is-props-and-how-to-use-it-in-react-da307f500da0#:~:text=%E2%80%9CProps%E2%80%9D%20is%20a%20special%20keyword,from%20one%20component%20to%20another.&text=Furthermore%2C%20props%20data%20is%20read,be%20changed%20by%20child%20components.

How to delete/set "null" nested property of state array in ReactJs Redux?

For example I have a site (location, not website). Under that there are 4 more "levels" of specification. For example lvl 1 - 2 - 3 - 4 can be "USA - New York - Brooklyn - streetX" or "CompanyA - buildingA - floorC - roomNumber".
I have to be able to delete the "lowest" specification level. So if you want to delete the roomNumber, because you moved an item to another room, floor etc... Only "roomNumber" should be deleted but "CompanyA - buildingA - floorC" should still exist in the state.
My API will return the last "level" so the record (with ID) of whatever is associated with "roomNumber". So, I have the ID to delete.
This is how my state looks:
So for example, I want to remove "lvl4test" level. Back-end wise I just send the ID, it deletes the record and on page-refresh (forced F5) it will realize this level is gone. But now in my reducer I don't know how to do it.
Here's my reducer:
case DELETE_SITE: {
console.log("delete site reducer reached");
return {
...state,
// somehow makes all "siteRows" == "undefined"
siteRows: state.siteRows.map((s) => {
if (s.siteLevel2Id && s.siteLevel2Id == action.payload.id)
s.siteLevel2Id = null;
if (s.siteLevel3Id && s.siteLevel3Id == action.payload.id)
s.siteLevel3Id = null;
if (s.siteLevel4Id && s.siteLevel4Id == action.payload.id)
s.siteLevel4Id = null;
if (s.siteLevel5Id && s.siteLevel5Id == action.payload.id)
s.siteLevel5Id = null;
})
}
}
If I do this, it will make all "siteRows" as "undefined" when React's trying to refresh?
I don't know if I should use "filter" but don't know how to do so on nested objects/foreach objects and then filter on their properties etc...
Basically, all I want is "siteLevel4Name" and "siteLevel4Id" to be "null" as well and then React refreshing state and my webpage. Does anyone know how to do this?
EDIT: in "action.payload" I get the item I want to delete, so "action.payload.id" for deleting "lvl4test" will be "d117c1f6-..."
.map have to return value, not just modify it. You return nothing, hence the undefined. At the end of your mapping function you should return new s value.
function reducer(state, action) {
return {
...state,
siteRows: state.siteRows.map((s) => {
if (s.siteLevel2Id && s.siteLevel2Id == action.payload.id)
return { ...s, siteLevel2Id: null };
if (s.siteLevel3Id && s.siteLevel3Id == action.payload.id)
return { ...s, siteLevel3Id: null };
if (s.siteLevel4Id && s.siteLevel4Id == action.payload.id)
return { ...s, siteLevel4Id: null };
if (s.siteLevel5Id && s.siteLevel5Id == action.payload.id)
return { ...s, siteLevel5Id: null };
return s;
}),
};
}

How to handle null values on first render?

I have a function which executes when the dropdown has a value of add or remove it will execute accordingly. However on the first render after I click the button it shows as 'added data'null. When I do it again it works. What would be the best way to handle this?
Here is my code:
Since I can't see any of the other code and there is no sandbox, I can only help you fix the issue of checking for null, however if we could see the component this function is in I could answer a lot more, however here is how you can check for null
const addtoproduction = () => {
let databaseChanges = unitTestsData.map(tests => {
return {
"unit_test_id": tests.unit_test_template_id,
"databases": tests.databases
}
})
setAddRemoveDatabaseChanges(databaseChanges)
if(AddRemoveDatabaseMode !== null && AddRemoveDatabaseMode === 'ADD'){
console.log('added data', AddRemoveDatabaseChanges);
} else if (AddRemoveDatabaseMode !== null && AddRemoveDatabaseMode === 'REMOVE') {
console.log('removed data', AddRemoveDatabaseChanges )
}
}

How can I change a data parameter in Angular 2?

I have a problem changing a data parameter in my component file:
this.commandList.ListesCommandesATransmettre.forEach(data => {
this.catalogs.forEach(catalog => {
if (catalog.Libelle === data.Catalogue) {
if (catalog.selected === false) {
console.log(data.isSelected)
data.isSelected = false;
console.log(data.isSelected)
console.log(data);
}
}
})
});
This code displays:
true
false
But the value of isSelected in console.log(data) is still true. So, why is the result false?
Try this if it's a loop problem with the callback
for (let data of this.commandList.ListesCommandesATransmettre) {
for (let catalog of this.catalogs) {
if (catalog.Libelle === data.Catalogue) {
if (catalog.selected === false) {
console.log(data.isSelected)
data.isSelected = false;
console.log(data.isSelected)
console.log(data);
}
}
}
}
I cant understand logic of your code. What happen if this.catalogs has many catalogs that meet the condition? isSelected will be setted many times in false.
Maybe this works (if I understand your logic):
this.commandList.ListesCommandesATransmettre = this.commandList.ListesCommandesATransmettre.map(data => {
const mutateData = Object.assign({}, data);
// If condition math, then isSelected set in false. Else, isSelected keep the his value
mutateData.isSelected =
this.catalogs.some(catalog => catalog.Libelle === data.Catalogue && !catalog.selected) ? false : mutateData.isSelected;
return mutateData;
})
Try this code to test if it is updating correctly. the loop will tell which are true/false and you can see if that is the case in the updated data.
this.commandList.ListesCommandesATransmettre.forEach((data, index) => {
this.catalogs.forEach(catalog => {
if (catalog.Libelle === data.Catalogue) {
if (catalog.selected === false) {
data.isSelected = false;
}
console.log(index + 'is selected: ' + data.isSelected)
}
})
});
console.log(this.commandlist);
Something I have noticed is that web browsers will only keep the the 'most current' reference of an object in memory. So after a loop has ended, the 'most current' reference is the last one to fire. So you may be looking at your last object and not the one you are trying to test. If someone else knows more, or has a reference to what is actually happening, please edit this post.

Resources