I have an application with different inputs. I want to access e.target.name of Switch, but i get undefined. For getting this i did:
const onChange = (name,e) => {
console.log(e.target.name)
}
and
<Switch defaultChecked onChange={e => onChange("test", e)} />
link to codesanbox: https://codesandbox.io/s/basic-usage-ant-design-demo-o3kro?file=/index.js:1198-1268
How to access Switch with e.target.name?
According to the docs(https://ant.design/components/switch/), I can see onChange takes the following format:
Function(checked: boolean, event: Event)
So In your code, you could pass the name attribute to your switch and access its current state(i.e checked) and also its event properties
const onChange = (checked, event) => {
console.log(checked, event.currentTarget.name);
};
<Switch defaultChecked name="test" onChange={onChange} />
The Switch component returns only trueor false.
If you do:
const onChange = (name,e) => {
console.log(e);
}
you can verify this.
If you want to acess the name "test" passed as argument, you just acess name parameter:
const onChange = (name,e) => {
console.log(name);
console.log(e);
}
**the switch return a boolean value on change **
const onChange = (name,checked) => {
console.log(checked)
}
and
<Switch defaultChecked onChange={checked => onChange("test", checked)} />
Related
i want to fix the eslinting rule error jsx no new function as prop using typescript and react.
i have code like below,
const Parent = () => {
const handleChange = useCallback((value: boolean) => {
setField(value);
}, [setField]);
return (
<RadioButton label="first" onChange={() => handleChange(true)}/> //error here
<RadioButton label="second" onChange={() => handleChange(false)}/> //error here
);
}
i understand that using onChange={() => handleChange(true)} is an anti pattern and hence the error . but i have tried
onChange={handleChange(true)} this causes maximum state update depth reached error.
how can i fix this such that i dont see the jsx no new function as prop error. could someone help me with this. thanks.
Just pass the callback as the prop:
<RadioButton label="first" onChange={handleChange}/>
Not 100% sure about your use case, but I'd recommend not using useCallback:
const handleChange = (value: boolean) => {
setField(value);
};
Also make sure that the RadioButton's onChange prop has the signature (value: boolean) => void and not using some sort of React.ChangeEvent. If it uses React.ChangeEvent, you will have to adjust the signature of handleChange.
try this
const Parent = () => (
<>
<WrapRadioButton label='first' bool />
<WrapRadioButton label='second' bool={false} />
</>
)
const WrapRadioButton = (props) => {
const [field,setField] = React.useState(false)
const handleChange = () => {
setField(props.bool);
};
return (
<RadioButton onChange={handleChange} {...props} />
);
};
const RadioButton =(props)=>{
const myProps = props
return (<div>lalal</div>)
}
I have an asynchronous Autocomplete component that works fine so far.
Hopefully the simplified code is understandable enough:
export function AsyncAutocomplete<T>(props: AsyncAutocompleteProps<T>) {
const [open, setOpen] = useState(false);
const [options, setOptions] = useState<T[]>();
const onSearch = (search: string) => {
fetchOptions(search).then(setOptions);
};
return (
<Autocomplete<T>
open={open}
onOpen={() => {
setOpen(true);
}}
onClose={() => {
setOpen(false);
}}
onChange={(event, value) => {
props.onChange(value as T);
}}
getOptionSelected={props.getOptionSelected}
getOptionLabel={props.getOptionLabel}
options={options}
value={(props.value as NonNullable<T>) || undefined}
renderInput={(params) => (
<TextField
{...params}
onChange={(event) => onSearch(event.currentTarget.value)}
/>
)}
/>
);
}
The component above works easily: when the user clicks on the input, the Autocomplete component displays an empty input field where the user can type in a value to search for. After the input has changed, the options are refetched to show matching results.
Now I want to add support for shortcodes: when the user types qq, the search term should be replaced by something, just like if the user would have typed something himself.
However, I found no way to update the value of the rendered TextField programmatically. Even if I set value directly on the TextField, it won't show my value but only the users input.
So, any ideas how to solve this problem?
Thank you very much.
What I've tried so far was to simply update the input within onKeyUp:
// ...
renderInput={(params) => (
<TextInput
{...params}
label={props.label}
onChange={(event) => onSearchChange(event.currentTarget.value)}
InputProps={{
...params.InputProps,
onKeyUp: (event) => {
const value = event.currentTarget.value;
if(value === 'qq') {
event.currentTarget.value = 'something';
}
},
}}
/>
)}
With the code above I can see the something for a short time, but it gets replaced by the initial user input very soon.
Autocomplete is useful for setting the value of a single-line textbox in one of two types of scenarios: combobox and free solo.
combobox - The value for the textbox must be chosen from a predefined set.
You are using it so it not allowing you to add free text (onblur it replaced)
Answer: To take control of get and set value programmatically.
you need a state variable.
Check here codesandbox code sample taken from official doc
Your code with my comment:-
export function AsyncAutocomplete<T>(props: AsyncAutocompleteProps<T>) {
... //code removed for brevity
//This is a state variable to get and set text value programmatically.
const [value, setValue] = React.useState({name: (props.value as NonNullable<T>) || undefined});
return (
<Autocomplete<T>
... //code removed for brevity
//set value
value={value}
//get value
onChange={(event, newValue) => setValue(newValue)}
renderInput={(params) => (
<TextInput
{...params}
label={props.label}
onChange={(event) => onSearchChange(event.currentTarget.value)}
InputProps={{
...params.InputProps,
onKeyUp: (event) => {
//get value
const value = event.currentTarget.value;
//if qq then set 'something'
if (value === "qq") {
setValue({ name: "something" });
}
//otherwise set user free input text
else {
setValue({ name: value });
}
},
}}
/>
)}
/>
);
}
React Checkbox not getting value onCheck . I tried an accepted answer, and get constant value first , but it is getting undefined(data variable)
<TableCell>
<Checkbox name="myCheckBox1" onChange={(e, data) => this.checkchange1('2', data.value)}/>
</TableCell>
checkchange1 = (e, data) => {
console.log('it works');
console.log(data.value);
}
what am I missing ?
To get the value of checkbox, Try like below
<Checkbox name="myCheckBox1" value="checkedA" onChange={(e) => this.checkchange1(e)}/>
checkchange1 = (e) => {
console.log(e.target.value); /* checkedA will be consoled here */
}
onChange will take only one param and that is e.
you can store the value in state like this.
<Checkbox onChange={this.toggle} checked={this.state.checked} />
toggle = () => this.setState(({checked}) => ({ checked: !checked }))
Usually my forms are super long, I would like to use them as components in separate files, I tried doing so but I can no longer modify the values, I mean there's two steps in this config,
first I need to pass initial values from the API fetch request, I used props like demonstrated below :
// in parent
<InvoiceDetails {...this.state} />
// in component
...
render() {
let { invoicenumber, ponumber, invoicedate, paymentdue, loading } = this.props;
return (
<div>
{!loading ?
<Form>
<Input fluid value={invoicenumber}
type="text" onChange={this.handleForm}
placeholder="Invoice number" name="invoicenumberEdit" />
<DateInput
autoComplete="off"
name="invoicedate"
placeholder="Invoice date"
dateFormat='MMMM Do YYYY'
value={invoicedate}
clearable icon={false}
clearIcon={<Icon name="remove" color="black" />}
onChange={this.handleInvoiceDate}
/>
...
The functions that update those inputs are changing the parent state, so I couldn't move them to the component file because that would be two separate states.
handleInvoiceDate = (event, { name, value }) => {
if (this.state.hasOwnProperty(name)) {
this.setState({ [name]: value });
}
}
handleForm = e => {
this.setState({ [e.target.name]: e.target.value });
};
I don't use context, redux or anything like that. How can I solve this if possible?
In your parent, make your handler a pure set state like this
handleInputChange = (name, value) => {
this.setState({ [name]: value });
};
then pass your handler as props like this
<InvoiceDetails {...this.state} handleInputChange={this.handleInputChange} />
then in your component, add these functions to your code
handleInvoiceDate = (event, { name, value }) => {
if (this.state.hasOwnProperty(name)) {
this.props.handleInputChange(name, value);
}
}
handleForm = e => {
this.props.handleInputChange(e.target.name, e.target.value);
};
Just pass your function's from parent to child component as a props like,
<InvoiceDetails {...this.state} handleForm={this.handleForm} handleInvoiceDate={this.handleInvoiceDate}/>
Function's in parent,
handleInvoiceDate = (name, value ) => {
if (this.state.hasOwnProperty(name)) {
this.setState({ [name]: value });
}
}
handleForm = (name, value) => {
this.setState({ [name]: value });
};
In your component call these function's like,
<Input fluid value={invoicenumber}
type="text" onChange={(e)=>this.props.handleForm(e.target.name,e.target.value)}
placeholder="Invoice number" name="invoicenumberEdit"
/>
<DateInput
...
onChange={(e)=>this.props.handleInvoiceDate(e.target.name,e.target.value)}
/>
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'))
}