How to update item in array using react? - reactjs

Could you please tell me how to update item in array using react? I make a dynamic list using add button. In generated Item I have two button update and delete.
On click of update button I change the text of add button to update and fill the selected value in input field. Now when I click update button I want to update the selected item.
Here is my code
https://plnkr.co/edit/bpSGPLLoDZcofV4DYxPe?p=preview
addName() {
if (this.state.username !== '') {
if (this.state.btnText === 'add') {
this.props.add(this.state.username)
} else if (this.state.btnText === 'update') {
this.props.updateItem(this.state.username)
}
this.setState({
username: '',
btnText: 'add'
})
}
}
delete(item) {
this.props.deleteItem(item)
}
update(item){
this.setState({
username : item,
btnText:'update'
})
}

You need to pass the updated item name and the indexof the item to the update case in the reducer. Then just use splice to update the new value
Updated the plunkr. Check it here
case 'UPDATE_ITEM':
let newList = state.slice()
newList.splice(action.payload.index, 1, action.payload.item)
return newList;

Related

How to keep the check box checked , when navigating to other page of react pagination

I want to ask , how to keep save the id's of the check boxes in a state , and whenever i switched back to first page it automatically search the element with id and mark check boxes automatically.
and if i unmark the checkbox , it deletes the id from the state.
i am able to think about the logic , but cant able to code,it
Small help ,will leads to solve this problem
While switching to other pages, i am succesfully saving the data ,by updating the state
`
// push all the unique objects (combination of previous state of selectedPayments and data from list)
setSelectedPayments((prevState) => {
var arr = [...prevState, ...list];
var newState = [
...new Map(arr.map((item) => [item.id, item])).values(),
];
return newState;
});
console.log('Selected payments are', selectedPayments);
`
Also , removing the objects , if again the checkbox is unchecked ,and updating the state
`
// pull all the objects , which got unChecked
setSelectedPayments((prevState) => {
var newState = prevState.filter(function (objFromA) {
return !list.find(function (objFromB) {
return objFromA.id === objFromB.id;
});
});
return newState;
});
`
Only facing issue with keeping track of the checked boxes, i have implimented this, this is keeping track of main(parent checkbox).
How to extract the ids saved and check the checkboxes when we naviagete from one page to another
`
let elementId = e.target.id;
if (selectedBoxes.includes(elementId)) {
const newArray = selectedBoxes.filter((e) => e !== elementId);
setSelectedBoxes(newArray);
} else {
setSelectedBoxes((prevState) => {
return [...prevState, elementId];
});
}
`
First i modified the Res Json , so that it set's a property isSelected = true,
by comparing the element from the selectedPayments
inAll check handler , i set the selectedPayments like this
And render using this
This is how ,i solved this problem.
** Better and improved answers are always welcome, please share your views.

Checkmark group of checkboxes based on array values

Forgive me there are a lot of questions asking this same thing but from over 10+ years ago.
Is there any way to checkmark a group of checkboxes based on an array in React? I have an array saved within state (stepThree) that I need to pulldown when a user returns to this screen within a multistep form. I'm looking for a way that the values within that array become/stay checked upon return to that screen so it shows the user their previous selections.
Current set-up explained below
State is opened with empty checkedBox array and stepThree initialized to pull responses later. checkedBox is eventually cloned into stepThree.
this.state = {
checkedBox: [],
stepThree: this.props.getStore().stepThree,
};
Boxes that are checked by the user are added to checkedBox array or removed if unchecked.
handleCheckboxChange = (event) =>{
const isChecked = event.target.value; //Grab the value of the clicked checkbox
if (this.state.checkedBox.includes(isChecked)) {
// If the checked value already exists in the array remove it
} else {
// If it does not exist, add it
}
}
Validate and store the completed array on clicking next
if (Object.keys(validateNewInput).every((k) => { return validateNewInput[k] === true })) {
if (this.props.getStore().stepThreeObjects != this.state.checkedBox) { // only update store of something changed
this.props.updateStore({
// Store the values of checkedBox inside stepThree and run updateStore to save the responses
});
} else {
// Return an error
}
Sample checkbox
<label className="choice-contain">
<span>Checkbox Sample</span>
<input
value="Checkbox Sample"
name="Question 3"
type="checkbox"
onChange={this.handleCheckboxChange}
/>
</label>
I've tried to create a persistCheckmark function that pulls the values of the array from stepThree and then does a comparison returning true/false like I do in the handler but since this is not an event I can't figure out how to trigger that function on return to the step.
Currently when returning to the step nothing is checked again and I believe that has to do with checkedBox being initiated as empty.
persistCheckmark(event) {
const isChecked = event.target.value; //Grab the value of the clicked checkbox
if (this.state.stepThree.includes(isChecked)) {
return true;
} else {
return false
}
}
Figured it out thanks to an old post here: How do I set a group of checkboxes using values?
Just updated the filter for when the component mounts
componentDidMount() {
if (this.state.stepThree != undefined) {
var isChecked = this.state.stepThree
$('input[type="checkbox"]').filter(function() {
return $.inArray(this.value, isChecked) != -1;
}).prop('checked', true);
} else { return }
}
and then added a ternary in the state initiation to check the storage and copy it over so it doesn't initialize as empty every time.
checkedBox: this.props.getStore().stepThree != undefined ? this.props.getStore().stepThree : [],

setting usestate hook for the array to [] (empty array) doesn't work

I'm trying to show products depends on the selected category tab. The first tab is 'show all' and its categoryId ="" I change the categoryId when tab changes. I show products by using shownMenuItems state (shownMenuItems.map(...)), and get all items from api first in useEffect hook and store this data into menuItems state.
I need to set shownItems to an empty array before every tab changing. So I can get rid of previous tab's products. I used setShownMenuItems([]) but this doesn't work. Isn't it immutable operation? I create a new array and set it to shownMenuItems.
useEffect(() => {
setShownMenuItems([]) //every time the tab changes, items will be shown is supposed to be cleared, and be filled after below conditions
if(categoryId===""){ //show all products tab's categoryId = ""
setShownMenuItems(menuItems) //sets shownMenuItems to all menu items
}else{
menuItems.forEach(menuItem=>{
if(menuItem.categoryId === categoryId){ //searches all menu items, looking for ones category id's match
setShownMenuItems([...shownMenuItems, menuItem])
}
})
}
}, [categoryId])
I thought this part of code is enough. If it doesn't, tell me to share more codes. Thanks.
Solution:
useEffect(() => {
setShownMenuItems([]) //every time the tab changes, items will be shown is supposed to be cleared, and be filled after below conditions
if(categoryId===""){ //show all products tab's categoryId = ""
setShownMenuItems(menuItems) //sets shownMenuItems to all menu items
}else{
menuItems.forEach(menuItem=>{
if(menuItem.categoryId === categoryId){ //searches all menu items, looking for ones category id's match
// setShownMenuItems([...shownMenuItems, menuItem])
setShownMenuItems(prev=>[...prev, menuItem])
}
})
}
}, [categoryId])
React collect all set state hooks inside useEffect and apply them together. Split this logic to two useEffect.
Also, for prevent not necessary rerender You need to filter all items and only after that all of them set as new state.
useEffect(() => {
setShownMenuItems([]) //every time the tab changes, items will be shown is supposed to be cleared, and be filled after below conditions
}, [categoryId]) ;
useEffect(() => {
if(categoryId===""){ //show all products tab's categoryId = ""
setShownMenuItems(menuItems) //sets shownMenuItems to all menu items
} else{
const filtered = menuItems.filter(menuItem => {
return menuItem.categoryId === categoryId;
});
setShownMenuItems(filtered) ;
}
}, [categoryId])

How do I get the value of a dynamic select field from another select field in React JS

https://codepen.io/abhilashn/pen/zYrEbyx
Above is my codepen where I select different state but I am not able set the first value of district on change
changeState(e) {
var state;
if(e.target.name == "state") {
state = e.target.value
this.setState({ defaultState: state, defaultDistrict: '' });
}
else if(e.target.name == "district"){
this.setState({ defaultState: this.state.defaultState, defaultDistrict: e.target.value })
}
else {
this.setState({ defaultState: this.state.defaultState,
defaultDistrict: this.state.defaultDistrict
})
}
this.getDataFromApi();
}
When I change the state i should immediately get the first option of district as defaultDistrict but I am setting it to ''.
This can be solved in two ways,
You can store the entire state_district_wise API response in component state. And get the districts info from that object based on the selected state from the dropdown and set the first district value as defaultDistrict
Another way in your getDataFromApi method once you fetch the response from API while updating the districts along with other data in the component state you can also update the defaultDistrict like below
this.setState({
districts: dists,
districtsData: dData,
districtConfirmedCases: confirmedCases,
districtActiveCases: activeCases,
districtDeceasedCases: deceasedCases,
districtRecoveredCases: recoveredCases,
confirmedCases: districtsConfirmedCases,
confirmedBgColor: districtsConfirmedBgColor,
activeCases: districtsActiveCases,
activeBgColor: districtsActiveBgColor,
deceasedCases: districtsDeceasedCases,
deceasedBgColor: districtsDeceasedBgColor,
recoveredCases: districtsRecoveredCases,
recoveredBgColor: districtsRecoveredBgColor,
...(!dists.includes(this.state.defaultDistrict) && {
defaultDistrict: dists[0]
})
});
Hope this helps.

How to check dynamically rendered checkboxes

I'm rendering some checkboxes dynamically, but currently I'm only able to check the first box, and all other boxes operate the first one. How do I get the boxes to work independently of each other?
This is typescript in React. I've tried changing the interface I'm referencing in the function, thinking I was referencing the wrong thing, but none of those worked.
This is the function:
handleCheckboxClick = (entitlement: IApiEntitlements, checked: boolean): void => {
if (checked === true) {
this.selectedEntitlementIDs.push(entitlement.id);
} else {
const index: number = this.selectedEntitlementIDs.indexOf(entitlement.id);
this.selectedEntitlementIDs.splice(index, 1);
}
//tslint:disable-next-line:prefer-const
let entitlementChecked: IEntitlementChecked = this.state.entitlementChecked;
entitlementChecked[entitlement.id] = checked;
let selectAll: boolean = false;
if (this.selectedEntitlementIDs.length === this.state.responses.apiResponses.apiClients.length) {
selectAll = true;
}
this.setState({
entitlementChecked: entitlementChecked,
selectAll: selectAll
});
console.log(this.selectedEntitlementIDs, 'hi');
console.log(entitlementChecked, 'hello');
}
And this is where it's being called:
return (
<Checkbox
checked={this.state.entitlementChecked[entitlement.id]}
data-ci-key={entitlement.id}
id='api-checkbox'
key={entitlement.id}
labelText={entitlement.label}
onChange={this.handleCheckboxClick}>
</Checkbox>
);
I expect each checkbox to be able to be checked, but currently on the first one works, and all others check or uncheck that first one.
You shouldn't keep an array as a property on the class that keeps track of selected items, this isn't tied to the React lifecycle and could potentially not update the view when you want to. Instead you should just use your map (entitlementChecked) you already have to determine if something is checked or not.
handleCheckboxClick(id) {
this.setState(prevState => ({
entitlementChecked: {
...prevState.entitlementChecked,
[id]: !prevState.entitlementChecked[id]
}
}));
}
When calling the handler method, you can just pass the id through that you need specifically.
onChange={this.handleCheckboxClick.bind(null, item.id)}
Here's a rudimentary example for more detail :)

Resources