Change multiple key values and setState in React - reactjs

How to change value all of keys "isVisible"?
state = {
players: [
{
id: 0,
name: 'Gabriel',
isVisible: false,
},
{
id: 1,
name: 'John',
isVisible: false,
},
]
I have tried:
handleclick = () => {
let players = this.state.players
players = players.map(player => player.set("isVisible", true))
this.setState({
players
})
}
It throw error because president.set is not a function. Any ideas?

try this:
handleclick = () => {
let players = this.state.players
players = players.map(player => {player.isVisible = true; return player;}))
this.setState({
players
})
}

Related

How can I delete an item inside a nested array with Hooks?

I am trying to remove a single item from state inside a nested array, but i am really struggling to understand how.
My data looks as follows, and I'm trying to remove one of the 'variants' objects on click.
const MYDATA = {
id: '0001',
title: 'A good title',
items: [
{
itemid: 0,
title: 'Cheddar',
variants: [
{ id: '062518', grams: 200, price: 3.00},
{ id: '071928', grams: 400, price: 5.50},
]
},
{
itemid: 1,
title: 'Edam',
variants: [
{ id: '183038', grams: 220, price: 2.50},
{ id: '194846', grams: 460, price: 4.99},
]
},
{
itemid: 2,
title: 'Red Leicester',
variants: [
{ id: '293834', grams: 420, price: 4.25},
{ id: '293837', grams: 660, price: 5.99},
]
}
]
}
Against each variant is a button which calls a remove function, which (should) remove the deleted item and update the state. However, this is not happening and I'm not sure what I am doing wrong.
const [myCheeses, setMyCheeses] = useState(MYDATA);
const removeMyCheese = (variantID, itemindx) => {
console.log(variantID);
setMyCheeses((prev) => {
const items = myCheeses.items[itemindx].variants.filter(
(variant) => variant.id !== variantID
);
console.log(items, itemindx);
return {
...myCheeses.items[itemindx].variants,
items
};
});
};
An example of the issue I'm facing can be seen here
https://codesandbox.io/s/funny-dan-c84cr?file=/src/App.js
Any help would be truly appreciated.
The issue is that, setMyCheeses function not returning the previous state including your change(removal)
Try one of these functions;
1st way
const removeMyCheese = (variantID, itemindx) => {
setMyCheeses((prev) => {
const items = myCheeses.items[itemindx].variants.filter(
(variant) => variant.id !== variantID
);
const newState = prev;
newState.items[itemindx].variants = items;
return {...newState};
});
};
https://codesandbox.io/s/bold-worker-b12x1?file=/src/App.js
2nd way
const removeMyCheese = (variantID, itemindx) => {
setMyCheeses((prev) => {
const items = myCheeses.items.map((item, index) => {
if (itemindx === index) {
return {
...item,
variants: item.variants.filter(
(variant) => variant.id !== variantID
)
};
} else {
return item;
}
});
return { ...prev, items: items };
});
};
https://codesandbox.io/s/sharp-forest-qhhwd
try this function, it's work for me :
const removeMyCheese = (variantID, itemindx) => {
//console.log(variantID);
const newMyCheeses = myCheeses;
const newItems = newMyCheeses.items.map((item) => {
return {
...item,
variants: item.variants.filter((variant) => variant.id !== variantID)
};
});
setMyCheeses({ ...newMyCheeses, items: newItems });
};
https://codesandbox.io/s/jolly-greider-fck6p?file=/src/App.js
Or, you can do somthing like this if you don't like to use the map function :
const removeMyCheese = (variantID, itemindx) => {
//console.log(variantID);
const newMyCheeses = myCheeses;
const newVariants = newMyCheeses.items[itemindx].variants.filter(
(variant) => variant.id !== variantID
);
newMyCheeses.items[itemindx].variants = newVariants;
setMyCheeses({ ...newMyCheeses });
};

TypeError: inputs.lineItems is undefined React

const [inputs, setInputs] = useState({
taxRate: 0.00,
lineItems: [
{
id: 'initial',
name: '',
description: '',
quantity: 0,
price: 0.00,
},
]
});
function handleInvoiceChange(e) {
//setInputs(inputs => ({...inputs,[e.target.name]: e.target.value}));
setInputs({[e.target.name]: e.target.value});
}
const calcLineItemsTotal = (event) => {
return inputs.lineItems.reduce((prev, cur) => (prev + (cur.quantity * cur.price)), 0)
}
const calcTaxTotal = () => {
return calcLineItemsTotal() + (inputs.taxRate / 100)
}
and this is how i handle the change
const handleLineItemChange = (elementIndex) => (event) => {
let lineItems = inputs.lineItems.map((item, i) => {
if (elementIndex !== i) return item
return {...item, [event.target.name]: event.target.value}
})
setInputs(inputs => ({...inputs,[lineItems]:lineItems}));
//setInputs({lineItems})
}
const handleAddLineItem = (event) => {
setInputs({
lineItems: inputs.lineItems.concat(
[{ id: uuidv4(), name: '', description: '', quantity: 0, price: 0.00 }]
)
})
}
const handleRemoveLineItem = (elementIndex) => (event) => {
setInputs({
lineItems: inputs.lineItems.filter((item, i) => {
return elementIndex !== i
})
})
}
this is a react application of an invoice generator the problem occures when i add the taxrate then i get that error
Updated values to states with hooks are not merged but replaced.
Also if you are using a version of v16 or lower of react know that Synthetic event is pooled by react, i.e event object is cleared before state callback runs.
Check here for more information.
The SyntheticEvent objects are pooled. This means that the
SyntheticEvent object will be reused and all properties will be
nullified after the event handler has been called.
The correct way to update your state is as below where you use function way to update state and copy the event values you need to separate variables outside of the setInputs function call
const name = e.target.name;
const value = e.target.value;
setInputs(inputs => ({...inputs,[name]: value}));
The rest of your function updates will be as below
const handleAddLineItem = (event) => {
setInputs(input => ({
...input,
lineItems: inputs.lineItems.concat(
[{ id: uuidv4(), name: '', description: '', quantity: 0, price: 0.00 }]
)
}));
}
const handleRemoveLineItem = (elementIndex) => (event) => {
setInputs(input =>({
...input,
lineItems: inputs.lineItems.filter((item, i) => {
return elementIndex !== i
})
}));
}

Change variable in array of objects in state React

What I wanted to do is whenever I click button to change variable in states array of objects. I did it this way, but is there any easier way to do it?
completeItem = (id) => {
const item = this.state.items.filter(el =>{
return el.id === id;
});
item[0].isCompleted = true;
const state = this.state.items;
const arr = this.state.items.filter(el =>{
if(el.id === id){
state[id-1] = item[0];
}
return state;
});
this.setState({
items:[...arr],
});
}
Try this solution...
completeItem = (id) => {
const items = this.state.items.filter(el =>{
if(el.id === id){
el.isCompleted = true;
}
return el;
});
this.setState({
items : [...items],
});
}
If the solution is helpful please let me know!
May compromise a little performance, but it is more readable.
completeItem = (id) => {
const newList = [...this.state.items]
const index = newList.findIndex(el => el.id === id);
newList[index].isCompleted = true
this.setState({ items: newList });
}
Here is how you can do it:
const items = [{
id: 1,
name: "one",
isCompleted: false
},
{
id: 2,
name: "two",
isCompleted: false
},
{
id: 3,
name: "three",
isCompleted: false
},
{
id: 4,
name: "four",
isCompleted: false
}
]
completeItem = (id) => {
const result = items.map(e => {
if (e.id === id) {
return { ...e,
isCompleted: true
}
} else {
return e;
}
});
console.log(result)
}
completeItem(2)

How to map trough array of object and toggle boolean property selected

I have state in React functional component. It is and array of objects. Every object in that collection has property "selected", which is a boolean. That array looks like this:
const [filterOptions, setFilterOptions] = useState([
{
title: 'highest',
selected: true,
},
{
title: 'lowest',
selected: false,
},
]);
After handleFilter func is executed I need to set state so this array has same title properties but reverse (toggle) selected properties.
This is handleFilter func in which I need to toggle every selected property of array objects:
const handleFilter = () => {
setFilterOptions();
};
function App() {
const [filterOptions, setFilterOptions] = useState([
{
title: 'highest',
selected: true,
},
{
title: 'lowest',
selected: false,
},
]);
const handleFilter = (e) => {
let newArr = [...filterOptions];
let value = e.target.value;
if (value === "lowest") {
newArr[0].selected = true;
newArr[1].selected = false;
} else if (value === "highest") {
newArr[0].selected = false;
newArr[1].selected = true;
}
setFilterOptions(newArr)
};
return (
<div>
<select onChange={handleFilter}>
<option value="lowest">a</option>
<option value="highest">b</option>
</select>
{console.log((filterOptions))}
</div>
);
}
please check hope it will work
var arryObj =[
{
title: 'highest',
selected: true,
},
{
title: 'lowest',
selected: false,
},
]
const handleFilter = (index,value) => {
arryObj[index].selected = value
};
handleFilter(0,false)
console.log(arryObj)
handleFilter(1,true)
console.log(arryObj)
You can pass a function into setFilterOptions to change the state based on the previous state.
const handleFilter = () => {
setFilterOptions(prevState =>
prevState.map(obj => ({...obj, selected: !obj.selected}))
);
};

Chartjs populate data with Axios response

I am attempting to have the data on the chart populate based on the set of data the user selects i.e past 24-hours, past week, etc. I am saving the data and the labels in state. The labels update according to the selected time frame, but none of the data populates. I have console logged the data (this.state.data.datasets[0].data[0]) and it is the correct data.
Here is my code:
class ChartDemo extends Component {
state = {
target: 20,
timeFrame: "past-hours",
totalSales: [],
data: {
labels: [],
datasets: [
{
label: "",
backgroundColor: "",
// data results
data: []
}
]
},
chartIsLoaded: false,
}
getData = (start, end) => {
API.getData(start, end)
.then(res =>
this.setState(state => {
// if any sales have occured in selected time period
if (res.data[0] !== undefined) {
let total = res.data[0].profit.toFixed(2);
let totalString = total.toString();
const totalSales = state.totalSales.concat(totalString);
return {
totalSales
};
} else {
// set to zero if no sales
const noSale = "0.00";
const totalSales = state.totalSales.concat(noSale);
return {
totalSales
};
}
})
)
.catch(error => console.log( error));
}
UNSAFE_componentWillMount() {
this.setTimeFrame();
}
setTimeFrame() {
const day-one = 2019-08-01;
const day-two = 2019-08-02;
const timeFrame = this.state.timeFrame;
this.setState({ target: 20 });
if (timeFrame === "past-hours") {
this.getData(day-one, day-two);
if (this.state.totalSales.length < 8) {
this.setState({ target: 7, chartIsLoaded: true });
setTimeout(
function () {
this.setState(prevState => ({
data: {
...prevState.data,
labels: [
timeset-one,
timeset-two,
timeset-three,
timeset-four,
timeset-five,
timeset-six,
timeset-seven,
timeset-eight,
],
datasets: [{
...prevState.data.datasets,
label: "24-hour Profit in $",
backgroundColor: "rgb(1,41,95)",
data: [this.state.totalSales]
}]
}
}))
}.bind(this), 1000
)
}
}
}
I solved this by removed the [] around this.state.totalSales. I was essentially putting an array into another array.

Resources