React Select OnChange by Index - reactjs

Can anyone help me im stuck at React Select Onchange by Index
<Select
name="taskTitle"
value={resultTitle[idx]}
onChange={this.handleChange(idx)}
options={optionResultTask}
/>
handleChange = idx => e => {
const { name, value } = e.target;
console.log(idx);
const task_results = [...this.state.task_results];
task_results[idx] = {
[name]: value
};
this.setState({
task_results
});
};
Codesandbox
My OnChange Function got error
Thanks.

Here's how I did it.
My select (rendered inside of a UI that can have N number of children, built by mapping over it):
{data.items.map((item, index) =>
<Select
options={dogFoodOptions}
isMulti={false}
name="dogfood"
id="dogfood"
value={item.value}
onChange={handleDogFoodChange(index)}
/>
}
The function:
const handleDogFoodChange = index => (option) => {
console.log(`index: ${index}, value: ${JSON.stringify(option)}`)
}

React Select onChange handler is called with the selected option as parameter (not an event), so change your code to something like this :
handleChange = idx => selected => {
console.log(idx, selected);
const { label, value } = selected;
// rest of your code
};

Related

Rsuite TreePicker clear selections programmitacally - ReactJS

I am using TreePicker & CheckTreePicker from rsuite package.
I would like to clear the selections programmatically for the tree picker when certain props value is changed. I am able to trigger event in the useEffect when value of selectItemchanges , and I would like to clear all the current selections for treePicker just after it.
const Categories = ({ selectItem }) => {
useEffect(() => {
// INCLUDE LOGIC HERE TO RESET ALL THE FILTERS WHEN the value of selectItem change
}, []);
const handleCategFilters = (value) => {
console.log("do something here with value", value);
};
return (
<CheckTreePicker
data={pickerDT}
onChange={(i) => {
handleCategFilters(i);
}}
/>
);
};
I appreciate yur help. Thank you.
You can manually control the value
const Categories = ({ selectItem }) => {
const [value, setValue] = React.useState([]);
useEffect(() => {
// INCLUDE LOGIC HERE TO RESET ALL THE FILTERS WHEN the value of selectItem change
setValue([]);
}, []);
const handleCategFilters = (value) => {
console.log("do something here with value", value);
};
return (
<CheckTreePicker
data={pickerDT}
value={value}
onChange={(i) => {
handleCategFilters(i);
}}
/>
);
};

Searchbar cause input unchecked

I have a ul that displays users with a checkbox input. When searching for a user by surname/first name, the previously selected input checkboxes are removed. How to prevent it?
function App() {
let copyList = useRef();
const [contacts, setContacts] = useState([]);
useEffect(() => {
fetch(api)
.then((res) => res.json())
.then((data) => {
copyList.current = data;
setContacts(copyList.current);
})
.catch((err) => console.log(err));
}, []);
contacts.sort((a, b) => (a.last_name > b.last_name ? 1 : -1));
const searchHandler = (value) => {
const contactsList = [...copyList.current].filter((x) => {
if (value.toLowerCase().includes(x.last_name.toLowerCase())) {
return x.last_name.toLowerCase().includes(value.toLowerCase());
} else if (value.toLowerCase().includes(x.first_name.toLowerCase())) {
return x.first_name.toLowerCase().includes(value.toLowerCase());
} else if (value === "") {
return x;
}
});
setContacts(contactsList);
};
return (
<div className="App">
<Header />
<SearchBar onSearch={(value) => searchHandler(value)} />
<ContactsList contacts={contacts} />
</div>
);
}
Input component is in ContactsList component.
function Input(props) {
const [isChecked, setIsChecked] = useState(false);
const [id] = useState(props.id);
const handleChange = () => {
setIsChecked(!isChecked);
console.log(id);
};
return (
<input
type="checkbox"
className={style.contact_input}
checked={isChecked}
onChange={handleChange}
value={id}
/>
);
}
When you filter the contacts and update the contacts state, the list in ContactList will be re-rendered as it is a new array which means you will have a new set of Input components with the default state. In order to persist the previously selected items you will also have to store the array of selected IDs in state. The Input component should receive the isChecked and onChange values from props so you can pass in a condition where you check if the current ID is in the list of selected IDs which means it is checked and when the user clicks on it, you can just simply update that array by adding the ID if it's not currently in the array or removing from it if it is already present (copying the array first since it's a state variable).

React form checkbox delete or add, does not update on first interaction

I have a form and checkbox's that I create from an array using map. The point of the checkboxes is if checked remove item from array if not checked add it back to array. So every onChange I check if it is checked or not and do that work, but the way it works now is the first checkbox I check it will not remove or add the item, but after that it will work like its supposed to work.
const {query} = useRouter();
let queryCopy = JSON.parse(JSON.stringify(query));
const [stateEditedQuery, setStateEditedQuery] = useState(query);
const tagDeletion = (e, tag) => {
console.log(e, tag);
if(e) {
let index = query.tags.indexOf(tag);
query.tags.splice(index, 1);
} else {
if(query.tags.indexOf(tag) === -1) query.tags.push(tag);
}
setStateEditedQuery(query);
console.log("THIS HRERE", query.tags);
};
<fieldset>
<legend>Delete Tags</legend>
{query.tags?.map((tag, index) => {
return (
<Checkbox
labelText={tag}
id={index}
key={index}
onChange={(e) => tagDeletion(e, tag)}
/>
)
})}
</fieldset>
So this is a relatively common problem including the useState hook, what you should do is update the current state like so:
const [value, setValue] = useState<string[]>([]);
const handleChange = (id: string) => {
setValue(curr =>
curr.includes(id)
? // when checkbox is already checked
curr.filter(x => x !== id)
: // when checkbox is to be checked
[...curr, id]
);
};
if you are not using Typescript, just omit the type definitions. Default state should be handled just by checking if
value.includes(id).

Setstate not updating in CustomInput type='checkbox' handler

This is the render method, how i am calling the handler and setting the reactstrap checkbox.
this.state.dishes.map(
(dish, i) => (
<div key={i}>
<CustomInput
type="checkbox"
id={i}
label={<strong>Dish Ready</strong>}
value={dish.ready}
checked={dish.ready}
onClick={e => this.onDishReady(i, e)}
/>
</div>))
The handler for the onClick listener, I've tried with onchange as well but it apears that onchange doesnt do anything, idk why?
onDishReady = (id, e) => {
console.log(e.target.value)
var tempArray = this.state.dishes.map((dish, i) => {
if (i === id) {
var temp = dish;
temp.ready = !e.target.value
return temp
}
else {
return dish
}
})
console.log(tempArray)
this.setState({
dishes: tempArray
});
}
The event.target.value isn't the "toggled" value of an input checkbox, but rather event.target.checked is.
onDishReady = index => e => {
const { checked } = e.target;
this.setState(prevState => {
const newDishes = [...prevState.dishes]; // spread in previous state
newDishes[index].ready = checked; // update index
return { dishes: newDishes };
});
};
The rendered CustomInput reduces to
<CustomInput
checked={dish.ready}
id={i}
label={<strong>DishReady</strong>}
onChange={this.onDishReady(i)}
type="checkbox"
/>
No need to pass in a value prop since it never changes.
Note: Although an onClick handler does appear to work, semantically it isn't quite the correct event, you want the logic to respond to the checked value of the checkbox changing versus a user clicking on its element.
You can do it this way:
this.setState(function (state) {
const dishes = [...state.dishes];
dishes[id].ready = !e.target.value;
return dishes;
});

event.currentTarget.name returning as currentTarget

I have a handleChange function in typescript that I call within another function to send the value of changes in a text field to a mobx tree. However, when I set const { name } = event.currentTarget and later log it in the function, the name variable is coming back as 'currentTarget' instead of the name attribute I assign in in my renderHexTextField function, and the value is undefined.
I render a number of different text fields by calling the renderHexTextField function, which takes in two params. The first is the value of the
If it was working as intented, the name variable would equal the 'hoverFontColor' string from my return statement, which would then be passed into handleChange as a key for the css object, and value would manipulate the mobx state tree.
Any help is appreciated!
edit** I forgot to mention that the TextField component is a MaterialUI component
SOLUTION EDIT** -- My handleChange was bound to a debounce. I had to update my onChange component attribute so event.persist() ran before this.handleChange. Thank you Praveen and Chris!
return (
this.renderHexTextField(css.hoverFontColor, 'hoverFontColor')
)
private renderHexTextField(input: string, name: string) {
// name parameter used to specify which state in handleChange function
if (name === 'fontType' || this._throwHexErr(input) === 'True') {
// If hex format is correct, render normal text field
return (
<TextField
required={true}
id="standard-required"
margin="normal"
name={name}
placeholder={input}
onChange={this.handleChange}
/>
)
} else {
// else render error text field
return (
<TextField
error={true}
id="standard-error"
margin="normal"
name={name}
placeholder={input}
onChange={this.handleChange}
/>
)
}
}
private handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
const { name, value } = event.currentTarget
const { store } = this.props
const currentBot = store.bots.current
if (currentBot) {
const id = currentBot._id
const css: any = toJS(currentBot.theme.css)
log('css obj >> ', css)
if (css) {
css[name] = value
log('handleChange >>> ', name, value, css)
currentBot.patchCSS(id, css)
}
} else {
log('No current bot in handleChange')
}
}
private _validateHex(hexcode: string, regex: any) {
// Regex Testing Function
log('validating hex')
return regex.test(hexcode)
}
private _throwHexErr(userInput: string) {
// Return True or Error depending on result of Regex Test
const regex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/
if (this._validateHex(userInput, regex)) {
return 'True'
} else {
return 'Error'
}
}
I have had the same trouble recently, I have used React.FormEvent<HtmlInputElement>. That gives me event.currentTarget.name from the interface. Does that help?
So just to elaborate, try changing React.ChangeEvent<HTMLInputElement> to React.FormEvent<HtmlInputElement>.
I think you need to change
const { name, value } = event.currentTarget
to
const { name, value } = event.target
or
const name = event.target.name;
const value = event.target.value;
This should work fine
private handleChange = (event: any): void => {
const name = event.target.name;
const value = event.target.value;
const { store } = this.props
const currentBot = store.bots.current
if (currentBot) {
const id = currentBot._id
const css: any = toJS(currentBot.theme.css)
log('css obj >> ', css)
if (css) {
css[name] = value
log('handleChange >>> ', name, value, css)
currentBot.patchCSS(id, css)
}
} else {
log('No current bot in handleChange')
}
}
also, do
<TextField
error={true}
id="standard-error"
margin="normal"
name={name}
placeholder={input}
onChange={(event) => this.handleChange(event)}
/>
See my solution edit above. My handleChange function was bound to a debounce, so I had to include event.persist() in the onChange attribute.
use e.currentTarget.getAttribute('name')
example:
const handleClick = (e) => {
console.log(e.currentTarget.getAttribute('name'))
}

Resources