Checkbox doesn't toggle when rendered from a function - reactjs

This is a little bizarre of a problem and I haven't been able to track down the issue. I have a checkbox / input combo I created using Semantic-UI React (Form.Checkbox). The checkbox portion is added to the input, think addon, for a little combo input situation. Desired behavior is when the checkbox is checked it allows the user to type input into the input portion of the combo input. The checkbox's state is managed in the component's local state.
If I just include this code:
<Form.Field className="field">
<label>{field.label}</label>
<Input
{...field.input}
label={{ basic: true, content: <Checkbox
onChange={() => this.setState({sendEmail: !this.state.sendEmail})}
checked={this.state.sendEmail} />,
style: {'borderRight': '0px'}
}}
disabled={!this.state.sendEmail}
labelPosition='left'
placeholder='Email Address'
/>
</Form.Field>
in the jsx (render function) for the component, the toggling actually happens, state is managed properly etc. But when I put the same code into a function to render back the same input like so:
renderCheckboxInputField(field){
return(
<div>
<Form.Field className="field">
<label>{field.label}</label>
<Input
{...field.input}
label={{ basic: true, content: <Checkbox
onChange={() => this.setState({sendEmail: !this.state.sendEmail})}
checked={this.state.sendEmail} />,
style: {'borderRight': '0px'}
}}
disabled={!this.state.sendEmail}
labelPosition='left'
placeholder='Email Address'
/>
</Form.Field>
</div>
);
}
and call it from here:
<Grid.Column>
<Field
name="email"
label="Send Email"
component={this.renderCheckboxInputField}
/>
</Grid.Column>
the checkbox doesn't actually visually toggle, though the state is being updated properly. You might ask why not just keep it in the first location where it already works, but a) for reusability I placed it within the function, and b) I wanted to include it this way inside of the <Field /> component at the bottom because I am using Redux Form for validation on the input portion of the checkbox / input combo I made.
So for some clarification the <Field /> component comes from Redux Form. The <Form.Field /> pertains to a Semantic-UI React component. And all of the hacky stuff inside of the <Input /> component's label field is me just customizing the input to look as I desire.

You are calling this.renderCheckboxInputField without any params, but in function definition you pass 'field' and using it inside

Related

React Hook Form Controller and React-Bootstrap Form.Check radio

I'm using React Hook Form and React-Bootstrap and I'm trying to set up a radio button group.
Radio 1 should be selected by default and then the user can switch between them.
Because I'm using Form.Check from React-Bootstrap I'm wrapping it in a React Hook Form Controller (Wrapper component for controlled inputs).
It should look like this:
This works fine for all the normal text inputs:
<Controller
control={control}
name="name"
defaultValue=""
render={({ field: { onChange, value, ref } }) => (
<Form.Control
type="text"
onChange={onChange}
placeholder="Name"
value={value}
isInvalid={!!errors.name}
ref={ref}
/>
)}
/>
But for radio boxes this doesn't seem to work. It's rendered without a default checked box, I can select both of them, and the submitted data is always the same.
Here's the code for the radio boxes:
Controller
control={control}
name="myradiovalue"
defaultValue="radio1"
render={({ field: { onChange } }) => (
<>
<Form.Check
onChange={onChange}
type="radio"
label="Radio 1"
id="formAdapterRadio1"
value="radio1"
/>
<Form.Check
onChange={onChange}
type="radio"
label="Radio 2"
id="formAdapterRadio2"
value="radio2"
/>
</>
)}
/>
How should this look? Separate Controllers maybe?

React-Final-Form delays in taking input with render props in Field

I am currently working on a react project. I am using react-final-form for fetching the data in the form. As I am using the material UI component to create the form I am creating the form somewhat like this.
Code
<Form
onSubmit={onSubmit}
validate={validate}
render={({ handleSubmit, values }) => (
<form onSubmit={handleSubmit}>
<FormControl variant="outlined" className={classes.formControl} key={fieldKey}>
<Field
name={field.fieldName}
render={({ input }) => (
<TextField
{...input}
className={classes.textField}
variant="outlined"
label={props.field.label}
placeholder={props.field.description}
required={props.field.isMandatory}
InputLabelProps={{
shrink: true,
}}
/>
)}
type="text"
/>
</FormControl>
</form>
)}
/>
Now as soon as I remove the input props from the render props it is working fine. but with the input props, it delays in taking input. Without input props, I could not fetch the value from the form.
Is there any way to resolve this time delay?
Thanks in advance.
If you want a simple field. Maybe you can pass on only essential props.
<TextField
name={input.name}
value={input.value}
onChange={input.onChange}
/>
The solution to this is subscriptions.
The form is initially rendered on every action, react-final-form allows to handle subscription,
<Form subscription={{handeleSubmit: true}} ...> </Form>
We can do somewhat like this
There is a video link for this. Video
Hope you find this helpful 😉

Can't submit TextField in Formik

Can't seem to find a reason why the first approach works, and the second doesn't.
Works: pastebin
Doesn't: pastebin
The difference between these two is that there's <TextField> in the second one instead of <div> and <Field>. But the examples I've seen makes the <TextField> work just fine, what am I missing?
You have to pass the component to <Field />:
<Field component={TextField} name="password">
You are now trying to use it like so:
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
render={props => (
<Form>
<TextField
id="name"
name="name"
label="Name"
value={props.values.name}
onChange={props.handleChange}
fullWidth
/>
</Form>
)}
/>
... Which should work, are you getting any errors in the console?
If that doesn't work for some reason you can try doing it via Field render props.
This snippet is taken from the Formik docs.
<Formik
...
<Field
name="lastName"
render={({ field }) => (
<input {...field} placeholder="password" />
)}
/>
...
/>
You see you can use a render props to the Field component to render a custom component if you like.
There are 3 ways to render things with <Field>.
Aside from
string-only component, each render prop is passed the same props for
your convenience.
Field's render props are an object containing:
field: An object containing onChange, onBlur, name, and value of the
field form: Formik state and helpers Any other props passed to field
See more in Formik docs here.

How to update the state in react outside a render method using a function

I am using a redux-form to submit data that user enters into a form-input to an api. The inputs of the redux-form are for editing the values of existing data in the form.So,what I want is to populate the input values of the form with the previous(existing) value which comes from the api.So,I used props to get the existing values and assign those values to the component state.And when the input changes, then I am changing the state for that input using setState. Now,the issue that I am facing is, since I am using redux-form, I am using Field component which comes from redux-form.So,this is how my render() method looks like:
render() {
const { handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<Field
label="Title for Post"
name="title"
component={this.renderField}
/>
<Field
label="Post Content"
name="body"
component={this.renderField}
/>
);
}
And the renderField() method which is used above looks as shown below:
renderField(field) {
return(
<div className="title-design">
<label className="label-design"> {field.label} </label>
<input
type="text"
className="title-input"
{...field.input}
value={this.state.title}
onChange={this.onInputChange}
/>
<div className="text-help has-danger">
{field.meta.touched ? field.meta.error : ''}
</div>
</div>
)
}
And the onInputChange() method looks like:
onInputChange(event) {
this.setState({title: event.target.value})
}
So,since my input is in the renderField() method,so when I try to type something in the input,I do not see the state updated(because my renderField() method is used as a prop and it is not in the render method,so state is not being updated), and that is the reason why my input is not working properly.I mean I am not able to insert or delete values in the input.
But,if I use the input as shown below inside my render method,it works properly as expected.
<input
type="text"
className="title-input"
value={this.state.title}
onChange={this.onInputChange}
/>
But,I don't know how to pass the values with only input as shown above to a redux-form.So, how to proceed with this? Can anyone please help me figure out?Thanks in advance.

How to grab Textfield input values with Redux-form using MaterialUI

Goal: Get the input values from a material UI component and pass them to an action creator in a handleSubmit function.
<Field name='email'
component={email =>
<TextField
fullWidth
autoComplete='off'
className={classes.textField}
id='email-text-field'
label='Email'
value={email} />
} />
<Field name='password'
component={password =>
<TextField
type='password'
fullWidth
autoComplete='off'
className={classes.textField}
id='password-text-field'
label='Password'
value={password} />
} />
This is how it is being connected to Redux:
#reduxForm({form: 'loginForm', fields: ['email', 'password']})
The warnings I'm getting in my chrome dev tools console is:
Failed prop type: Invalid prop value supplied to TextField.
Warning: Failed prop type: Invalid prop value supplied to Input.`
Additionally, the email field in my login form shows [Object, object}
My guess is that this is happening due to the fact that props are being passed from the
Any ideas on where I've gone wrong?
When you want to use a custom field for Redux-Form, Redux-form gives you access to both props like onChange etc, but also other meta-data (like if the form has been touched or not). These different kinds of props are grouped depending on type.
The interesting part for you is that all the attributes associated with a normal input element (like onChange, value, type) are grouped in props.input. So the argument you call password is actually the whole props object that is sent down to the component. It looks something like this {input:{ value: 'someValue', onChange: somFunction.. etc. etc}, meta: { touched: false, etc. etc.}}.
That means that if you want to use the TextField like you do now, you need to do something like:
<Field name='email'
component={({input}) =>
<TextField
value={input.value}
onChange={input.onChange}
fullWidth
autoComplete='off'
className={classes.textField}
id='email-text-field'
label='Email'
/>
} />
This can get pretty messy, especially if you want to use the meta props, so it's often worth it to break the custom component logic out into its own function, like they do in the example in the docs: https://redux-form.com/7.0.4/examples/material-ui/
You may also be interested to know that for material-ui components, there actually already exists a library that has done most of that manual work for you: redux-form-material-ui.

Resources