TextField values are equal to "undefined" in ReactJS - javascript

I am very new to ReactJs and Material-UI. Therefore I apologize if my question is dumb.
So, I have a file Main.js that contains the following lines of code:
handleChange = (name, event) => {
if(event==null)
return;
console.log(event)
this.setState({
[name]: event.value
}, () => {
console.log("my_num_var",this.state.my_num_var)
console.log("my_combobox_var",this.state.my_combobox_var)
});
};
Then, I have TopControls.js with the following code:
<Grid item xs={true}>
<TextField
name="my_num_var"
id="my_num_var"
label="my_num_var"
onChange={(event) => this.props.handleChange("my_num_var", event)}
value={this.props.state.my_num_var}
type="number"
className={this.props.styles.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start">(seconds)</InputAdornment>,
}}
/>
</Grid>
Each time when I change the value of my_num_var (TextField), I see undefined in console (console.log("my_num_var",this.state.my_num_var)).
In the handleChange function, the console.log(event) outputs:
SyntheticEvent {dispatchConfig: {…}, _targetInst: FiberNode,
nativeEvent: InputEvent, type: "change", target:
input#visibility.MuiInputBase-input-269.MuiInput-input-254.MuiInputBase-inputType-272.MuiInput-inpu…,
…}
So, basically event.value returns nothing. The value is set only if I do event.target.value. But in this case, the comboboxes do not work because they need event.value. How can I distinguish between the evnts?
The comboboxes work fine with event.value and I can see correct values of my_combobox_var in console.
<Grid item xs={true}>
<FormControl
className={this.props.styles.formControl}
margin="normal">
<InputLabel shrink htmlFor="my_combobox_var-label-placeholder">
my_combobox_var
</InputLabel>
<Select
onChange={(event) => this.props.handleChange("my_combobox_var", event)}
className="basic-single"
classNamePrefix="select"
defaultValue={this.props.state.my_combobox_var}
isClearable={this.state.isClearable}
isSearchable={this.state.isSearchable}
name="my_combobox_var"
options={this.t}
styles={myStyle}/>
</FormControl>
</Grid>
I am not sure if the code that I posted above is enough to help. If I should add more details, please let me know. I would appreciate any clues. Thanks.

Instead of passing the whole event to handleChange you could pass only the value to make it simpler.
Since the text input needs event.target.value instead of event.value this will allow you to use the same handler for multiple event types.
onChange={(event) => this.props.handleChange("my_num_var", event.target.value)
onChange={(event) => this.props.handleChange("my_num_var", event.value)
Then just rewrite your handler to expect the value instead of the event:
handleChange = (name, value) => {
if(value==null)
return;
this.setState({
[name]: value
},
...

Related

Material UI Autocomplete: highlighted option should become input value

When a user browses through the options using the arrow keys on his keyboard, I take the value from the highlighted option and use it as the current input value (input here has its own state).
Unfortunately, the highlighted state of the option is lost upon saving the title or value of the option as the input. Is there a way to not lose it?
Here is an example:
https://codesandbox.io/s/modern-rgb-5tew1p?file=/demo.tsx
P.S.:
Although this property sounded like it was made for it, includeInputInList does not help.
Thanks in advance!
Try this (I made some changes to your code like adding reason and isOptionEqualToValue):
export default function ComboBox() {
const [input, setInput] = React.useState(null);
const handleInputChange = (event, value) => {
setInput(value);
};
const handleHighlightChange = (event, option, reason) => {
if (option && reason === "keyboard") {
setInput(option);
}
};
const handleFilterOptions = (currentOptions) => currentOptions;
return (
<Autocomplete
id="combo-box-demo"
value={input}
onChange={handleInputChange}
options={top100Films}
isOptionEqualToValue={(option, value) => option.label === value.label}
includeInputInList={true}
onHighlightChange={handleHighlightChange}
getOptionLabel={(option) => option.label}
filterOptions={handleFilterOptions}
style={{ width: 300 }}
renderInput={(params) => (
<TextField {...params} label="Combo box" variant="outlined" />
)}
/>
);
}

useState and onChange with React Quill not working as I want it to, not sure how to fix

I have a series of text input fields - their input is managed by useState like this:
const [formFields, setFormFields] = useState([
{ textinput1: "", textinput2: "", textinput3: "", reactQuill: "" } ]);
Their handle change is managed with this function, because more text fields can be added, and every index of the additions has to have its input get saved:
function handleChangeInput(index, event) {
const values = [...formFields];
values[index][event.target.name] = event.target.value
setFormFields(values);
}
And this is what they look like and function as intended:
{
formFields.map((formField, index) => (
<React.Fragement key={index}>
<TextField
name='textinput1'
value={formField.textinput1}
onChange={event => handleChangeInput(index, event)}
/>
))
}
However, when I try the same exact logic with the React Quill (rich text editor) input, it's not working at all. So for example, this will not work:
<ReactQuill
name="reactQuill"
onChange={event => handleChangeInput(index, event)}
value={formField.reactQuill}
/>
I am getting an error of "name" being undefined, and I am not sure how to work around this? Thanks in advance if anyone knows how to fix this!
The issue was fixed. Since the React Quill text editor does not return a traditional event like other text fields do, my handleChangeInput had to be modified to:
function handleChangeInput(index, targetName, targetValue) {
const values = [...formFields];
values[index][targetName] = targetValue
setFormFields(values); }
And the onChange for text fields had to be changed to:
onChange={event => handleChangeInput(index, event.target.name, event.target.value)}
The onChange for React Quill had to be changed to:
onChange={value => handleChangeInput(index, 'reactQuill', value)}
I hope this helps someone in the future!

React TypeError: Cannot read properties of undefined (reading 'name')

I am using React with Material UI's Textfield components. Was trying to find out the best way to set the form states with the least redundancy. Like for example, I have 8 different input fields. Instead of having a seperate handler for each input, like for example handleFirstName, handleLastName, handleEmail, handleInfo, etc.
So to accomplish this, I tried to create a handleChange handler which looks like below:
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
});
}
And on each component,
<TextField
className={classes.formInput}
name="firstName"
onChange={e => this.handleChange(e.target.value)}
required
id=""
type="text"
InputLabelProps={{
shrink: true,
}}
error={!firstName}
helperText="Name is required"
label="First Name"
variant="standard" />
<TextField
className={classes.formInput}
name="lastName"
onChange={e => this.handleChange(e.target.value)}
required
id=""
type="text"
InputLabelProps={{
shrink: true,
}}
label="Last Name"
variant="standard" />
And here is my state object
constructor(props) {
super(props);
this.state = {
firstName: '',
lastName: '',
...,
};
}
These are just two of the input fields, but there are about 6 more fields that look the same. Any idea to combat this undefined name?
The problem is that you are not passing the complete event object. You are passing only the value. That is the reason why you are getting the name as undefined.
Try changing the onChange event to below -
onChange={this.handleChange}
This way you will get the complete event object in the function's e variable.
I think you need to handle multiple input field changes in single function.It is doable. try this
handleChange = (e)=>{
{name,value} = e.target;
this.setState({
[name]=value;
});
}
finally when to pass the onChange method to fields use :
onChange = {this.handleChange}

Fix .map is not a function in a functional component

I have a Textbox where I set array items to the textbox and I use it as a drop down. My code works and I am able to see the items in the drop down, however when i click on any other item apart from the first item I get the error groups.map is not a function.
I set array from the API to my groups and then I try to map the items that I need into the textbox.
Please see my code below and assist me to fix it.
I set my state to an empty array here
const [groups, setGroups] = useState([]);
const handleChange = event => {
setGroups({
...groups,
[event.target.name]: event.target.value
});
};
I handle my API call here
axios
.post('http://', formData, config)
.then((response) => {
console.log(response.data)
setGroups(response.data);
})
.catch((error) => {
console.log(error.response);
});
}, []);
I render with my data to show in the drop down here
<TextField
fullWidth
label="Select Group"
margin="dense"
name="groups"
onChange={handleChange}
required
select
// eslint-disable-next-line react/jsx-sort-props
SelectProps={{ native: true }}
value={groups.name}
variant="outlined"
>
{groups.map(option => (
<option
key={option.id}
>
{option.name}
</option>
))}
</TextField>
It is because axios is not done with the request and your state has not been updated yet when you try to map over your state. Try this piece of code near the map:
{groups && groups.map(option => (
<option
key={option.id}
>
{option.name}
</option>
))}
The map will go over the array only if groups exists
Try adding a new state variable to store the selected group.
const [selected, setSelected] = useState();
Your handleChange function will become something like
const handleChange = event => {
setSelected(event.target.value);
};
And your TextField component will have it's value changed to match the corresponding state variable:
<TextField
fullWidth
label="Select Group"
margin="dense"
name="groups"
onChange={handleChange}
required
select
// eslint-disable-next-line react/jsx-sort-props
SelectProps={{ native: true }}
value={selected}
variant="outlined"
>
{groups.map(option => (
<option
key={option.id}
>
{option.name}
</option>
))}
</TextField>
I had same problem look for response that you are getting if it is an object you can convert it to array in api by
Object.entries(images)
Then send this response also in client side when you request data set data with res.data otherwise it will be huge object.....

Is it possible use react-codemirror2 with formik?

I have a project and I use Formik and react-codemirror2, I want control the onChange in Formik but the onChange in codemirror2 don't have event...and i dont't know how to use...
let me explain better :
i have a formink:
<Formik
enableReinitialize
onSubmit={values =>
{this.submitFormDefinition(values)}}
initialValues={this.state}
>
{({ handleSubmit }) => (
<div>
<Form
onSubmit={handleSubmit}
autoComplete="off"
onChange={event => {
this.handleChange(event)
}}
>
<Field
component={CustomInputComponent}
name="name"
id="id"
multiline
/>
</Form>
</div>
)}
where I have my function handleChange:
handleChange = event => {console.log('change') ....}
an where the CustomInputComponent is my codemirror2 component:
const CustomInputComponent = ({ field, form, ...props }) => {
return (
<CodeMirror
id={props.id}
name={props.name}
value={this.state.value}
options={{
mode: 'javascript',
theme: 'default',
lineNumbers: true,
}}
{...props}
onBeforeChange={(editor, data, value) => {
console.log({ value })
this.setState({ jsonSchema: value })
}}
onChange={(editor, data, value) => {
?????????????
}}
/>
)
}
If I use another component as textField from Materia-UI it work i don't need to call on my CustomInputComponent the onChange , that is direct call by formink... because also the onChange of textField have as parameter event... but as you can see in the code the onChange of codeMirror doesn't have event...
I need to call the my handleChange and not onChange of codeMirror ...
I tried to do something like that:
<CodeMirror
onChange=form.handleChange
or use :
<CodeMirror
onKeyUp={form.handleChange}
or:
<CodeMirror
onKeyUp={(editor, event) => {
form.handleChange(event)
}}
but nothing works
my function handleChange is never call
How use react-codeMirror2 with Formik? is possible? how can I itercept the onChange of Formink?????
Formik's handleChange method expects an HTMLInput change event, and it gets the updated value from the input. Unfortunately, you don't get that convenience if you're using CodeMirror. However, CodeMirror provides the value of the component onBeforeChange, and Formik provides a setFieldValue method, which lets you imperatively set a value into state. So you can do this:
<Formik {...whateverPropsYouSet}>
(formikProps) => (
<CodeMirror
value={formikProps.values.yourDataField}
onBeforeChange={(_editor, _data, value) => {
formikProps.setFieldValue('yourDataField', value);
}
/>
)
</Formik>

Categories