How can i fill a array on state? - reactjs

Im using onError method to call this function:
And I need to set on state every time when onError method is executed.
brokenMobImg(e){
var image = e.target
image.parentNode.removeChild(image);
this.setState({broken: e.target.src})
console.log('IMGS:', this.state.broken);
}

You need to setup your errors as an array in state first then update the array with your new error rather than just replacing your broken variable each time. Here is a codesandbox example that does something similar to what you are wanting to do: https://codesandbox.io/s/currying-haze-cshem?fontsize=14

Current:
brokenMobImg(e){
var image = e.target
image.parentNode.removeChild(image);
this.setState({broken: e.target.src})
console.log('IMGS:', this.state.broken);
}
Solution:
constructor(props){
super(props);
this.state ={
broken:[]
}
}
brokenMobImg(e){
var image = e.target;
var brokenInState = this.state.broken;
image.parentNode.removeChild(image);
brokenInState.push(e.target.src);
this.setState({broken: brokenInState},()=>{
console.log('IMGS:', this.state.broken);
});
}

Related

updating one value in State array react native

Trying to update one element of an array in this.state I'm getting an (expected ,) error but cant see where I've gone wrong. Do I need to create a temporary array update that, then assign the whole array back to the state
This is essentially what I have
this.state = { array: ['a', 'b', 'c'] };
onBack() {
this.setState({
array[2]: 'something'
});
}
You can't update the state like this.
Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.
Read React docs.
You can do something like this :
let newArray = [...this.state.array];
newArray[2] = 'somethingElse';
this.setState({array: newArray});
The above example is using Spread Syntax.
There are multiple ways to modify state, but all the ways should ensure that data is treated as immutable. You can read more about handling state in React here
Manoj's answer will work, there is another way using the updater function (funtinal setState) for setState (which you can read about here)
onBack() {
this.setState(prevState => {
let newArray = prevState.array
newArray[2] = "something"
return { array: newArray }
});
}
Use Object.assign({});
let array= Object.assign({}, this.state.array); //creating copy of object
array[2]="something"
this.setState({array});
If you are bother to set the new updated array on your currentArray using spread function, you may use Array.from(duplicateArray)
let duplicateArray = [...currentArray] //duplicate the array into new array
duplicateArray[index].value = 'x'; // update the field you want to update
setCurrentArray(Array.from(duplicateArray )) //set the new updated array into currentArray
I bother with this issue and I just search about and I saw this idea, and it works!
https://github.com/facebook/react-native/issues/21734#issuecomment-433885436
using hooks
const [totalSet, setTotalSet] = useState(null);
console.log(totalSet); // {sets: Array(3), subscribed: false}
setTotalSet(datas => ({
...datas,
sets: updatedSet,
}));
Create a temporary array update that, then assign the whole array back to the state
var arr = [];
arr = this.state.array;
arr[2] = "something";
this.setState({
array : arr
});

Updating arrays in react component state

In the function below, I am trying to update the state of a react component; the animalMix item is an array. I take a copy, update it and then try to overwrite the original. I have checked that the new array (newAnimalsHeld) is updated correctly, but this is not reflected when i set animalMix in state equal to it.
The whole thing can be seen in context here:
https://codepen.io/timsig/pen/XVdbdo?editors=0010
Many thanks for any help.
removePair(){
console.log('Match!');
console.log(this.flipped);
let animalsHeld = [...this.state.animalMix];
let theMatch = this.flipped[0].props.animal;
let newAnimalsHeld = animalsHeld.map(function(animal){
if (animal.animal === theMatch) {
console.log('MATCH! Animal: ' + animal.animal + 'Match:' + theMatch);
return {};
}else{
return animal;
}
});
console.log('New Animals held: ', newAnimalsHeld);
this.setState({
animalMix: newAnimalsHeld,
doTurn: true
});
this.flipped = [];
console.log(this.state.doTurn, this.state.animalMix);
}
setState is an asynchronous function. However, you can print to console after state has updated in the following manner:
this.setState({
animalMix: newAnimalsHeld,
doTurn: true
},() => {console.log(this.state.doTurn, this.state.animalMix);});

Why is concat on array inside this.state not working?

I'm trying to add rendered dates inside of my array located in my component state under the key date, but it always returns 0.
constructor(props) {
super(props);
this.state = {
dates: []
}
}
componentWillMount() {
this.renderDateComp()
}
renderDateComp() {
for(var i = 0; i < 5; i++) {
var dat = new Date(Date().valueOf());
dat.setDate(dat.getDate() + i);
this.setState({ dates: this.state.dates.concat(dat) });
console.log(this.state.dates); //prints length of 0
}
}
Well firstly, state transitions aren't immediate, they are asynchronous (in most circumstances). Think of it like every time you set the state, it adds that state change to a queue of changes and React is continuously working through that queue, doing all those state changes. So if you change the state, then on the next line of code immediately print the state, the state probably won't have changed because the console.log happens IMMEDIATELY after the state change is added to the list, but BEFORE the change has actually gone through that queue.
Secondly, it's probably better to set the state AFTER the for loop, so you only have to set it once, not 5 times.
The recommended way to do it would be to:
Call setState only once after you have the final dates array.
Log this.state.dates in the callback of setState (it will only be called after this.state has been properly updated by React.
The key point to note here is that setState is asynchronous. You probably do not need to console.log the array in your real code.
Read more about setState here.
constructor(props) {
super(props);
this.state = {
dates: []
}
}
componentWillMount() {
this.renderDateComp()
}
renderDateComp() {
var dates = this.state.dates;
for (var i = 0; i < 5; i++) {
var dat = new Date(Date().valueOf());
dat.setDate(dat.getDate() + i);
dates = dates.concat(dat);
}
this.setState({
dates
}, () => {
console.log(this.state.dates); //prints length of 5
});
}
It's worth reading the documentation of setState(). https://facebook.github.io/react/docs/react-component.html#setstate
It will queue the change, but there is a callback version if you want to use the new value somehow.
this.setState((prevState, props) => {
return {myInteger: prevState.myInteger + props.step};
});
More specifically, if you do this:
this.setState({ dates: this.state.dates.concat(dat) }, () => console.log(this.state.dates));
You'll get the result you're expecting.

React change state in array (for loop)

I have a State with flights, and I have a slider to change the max price to change visibility of the flight elements.
maxpriceFilter() {
var flightOffer = this.state.flightOffer;
var sliderPrice = this.state.sliderPrice;
for (var i = 0; i < flightOffer.length; i++) {
if( flightOffer[i].price > sliderPrice) {
this.setState(
{[flightOffer[i].hiddenprice] : true}
);
};
}
This code is adding a undefined field with status true in the root of the state though.. I cant find any best practice on this, other then using computed fields. But I cant get the computed field working either..
Could someone please help me out here?
You don't want to do a setState call in a loop, that will have the react component render multiple times. Build a new state object and call the setState once. You also don't want to filter it out by an if statement, but set previous values to hidden:
maxpriceFilter() {
var flightOffer = this.state.flightOffer;
var sliderPrice = this.state.sliderPrice;
var newState = {};
for (var i = 0; i < flightOffer.length; i++) {
newState[flightOffer[i].hiddenprice] = flightOffer[i].price > sliderPrice;
}
this.setState(newState);
// ...
}
If you're still having issues, it could be that the hiddenprice property isn't what you expect? Might need to post your render() function as well.
Instead of doing your looping when you're updating the state, why not just do the switch on render?
You're probably already looping over all flightOffers in render(). So, just add the check there. Inside your render, pass hiddenPrice={offer.price > sliderPrice} as a prop, or use it directly where you control the visibility.
Why? Because the visibility of a specific item in this case is not state. It is a result of the state.

React JS - Function within Component cannot see State

In code below the onclick function testNewBug is unable to access the state of its parent component 'BugList'. Can anyone see where I have gone wrong with this, I am correctly setting the state and can view it in DevTools, surely with the function within the component 'this.state' should be working?
class BugList extends React.Component {
constructor() {
super();
this.state = {
bugs: bugData
}
}
render() {
console.log("Rendering bug list, num items:", this.state.bugs.length);
return (
<div>
<h1>Bug Tracker</h1>
<BugTable bugs={this.state.bugs} />
<button onClick={this.testNewBug}>Add Bug</button>
</div>
)
}
testNewBug() {
var nextId = this.state.bugs.length + 1;
this.addBug({id: nextId, priority: 'P2', status:'New', owner:'Pieta', title:'Warning on console'})
}
addBug(bug) {
console.log("Adding bug:", bug);
// We're advised not to modify the state, it's immutable. So, make a copy.
var bugsModified = this.state.bugs.slice();
bugsModified.push(bug);
this.setState({bugs: bugsModified});
}
}
Oh dear I was being and idiot, I forgot to bind my event handler to 'this'
<button onClick={this.testNewBug.bind(this)}>Add Bug</button>
if you know the method will always bind to the current class instance you can always define your method like this with =>:
testNewBug = () => {
var nextId = this.state.bugs.length + 1;
this.addBug({id: nextId, priority: 'P2', status:'New', owner:'Pieta', title:'Warning on console'})
}
you won't have to worry about bind(this) all over the place and this assures the function has one instance per class.

Resources