how to improve my coding standards to meet senior developer standards - reactjs

I just recently finished a tech test for a company applying for a frontend developer working in react and I was rejected with no feedback. So I was wondering what I could have done better and improved for next time. I've just recently tried to apply for seniors frontend roles. Here is the test they gave me and what I produced.
Here is the description of their test.
Create a component as a Form Control according to this design
The control should accept a label
The control should accept a validation function with configurable error message
The control can be incorporated inside a <form> and the selected option pushed up to the form.
The control should fire an event on change
Use the component you made in the previous step to create a form according to this design
Call this https://jsonplaceholder.typicode.com/users to populate list of the users. name should be displayed while id should be saved as the value in the form.
Add the required validation with the Please select a user error message.
Add 2 text fields, one for title and one for body both with required validation. (Don't worry about matching the design for the text fields.)
On submit of the form create a new post by sending the data to https://jsonplaceholder.typicode.com/posts. The request interface will look like
{
"title": "foo",
"body": "bar",
"userId": 1
}
This is what I produced:
https://codesandbox.io/s/objective-thunder-322xi?file=/src/components/FormComponent.js
I am aware it could have been better but there was a time limit and there was no feedback provided so I don't know where I went wrong. Could someone look through it please and see if it aligns with their instructions and where it could be improved.

I went through your code and may have found some codes which I may have implemented a little differently. I am not sure if this is the best coding standard but may have gone like this.
I see a lot of useStates declared there(7 declarations). I might have group some related states together. I have given an example for reference below. Using too many declarations may not be good in some cases.
The handleChange function (const handleTitleChange = (ev) => setTitle(ev.target.value);) can be improved. The way handled here is repeating for every input. So, if I have 10 inputs, there will be 10 lines for handleChange function. I gave a better way of handling change in my example. Remember to put the same 'name' attribute in the input field and the state. This code will save you a lot of time in future handling onChange and also clean code
I see you use 'id' attribute to refer to DOM elements in the form. This is good for vanilla JS but in React, it is preferred not to use. There is a better way in react called creating a reference, i.e. React.createRef(). This provides an easy reference to the DOM elements. Please refer to my example below.
The validation handling method can be improved. Code in example.
I see the error message does not go away once you fill content. So, this needs to be changed.
I have managed to come up with another way to implement which is totally dependent on states for form validation handling.
CODE WITH CREATE REF Don't mind the CSS classes, I used bootstrap
import React, { useState, useEffect } from 'react';
const TestComponent = () => {
const [input, setInput] = useState({
title: '',
body: '',
})
const titleRef = React.createRef()
const bodyRef = React.createRef()
const handleChange = e => {
setInput({ ...input, [e.target.name]: e.target.value })
}
const onHandleSubmit = e => {
e.preventDefault();
input.title ? titleRef.current.innerHTML = '' : titleRef.current.innerHTML = 'Please add a title';
input.body ? bodyRef.current.innerHTML = '' : bodyRef.current.innerHTML = 'Please add a body';
if (!input.title || !input.body) {
return false;
}
console.log('Submit your form');
}
return (
<div className="container py-5">
<form onSubmit={onHandleSubmit}>
<label>Title</label>
<input type="text" name="title" value={input.title} onChange={handleChange} className="form-control" />
<p ref={titleRef} style={{ color: 'red' }}></p>
<label>Body</label>
<input type="text" name="body" value={input.body} onChange={handleChange} className="form-control" />
<p ref={bodyRef} style={{ color: 'red' }}></p>
<button>Submit</button>
</form>
</div>
);
}
export default TestComponent;
CODE WITH STATES FOR VALIDATION
import React, { useState, useEffect } from 'react';
const TestComponent = () => {
const [input, setInput] = useState({
title: '',
body: '',
titleError: '',
bodyError: '',
})
const handleChange = e => {
setInput({ ...input, [e.target.name]: e.target.value })
}
const onHandleSubmit = e => {
e.preventDefault();
setInput({
...input,
titleError: input.title ? '': 'Please add a title',
bodyError: input.body ? '': 'Please add a body',
})
console.log(input);
if (!input.title || !input.body) {
return false;
}
console.log('Submit your form');
}
return (
<div className="container py-5">
<form onSubmit={onHandleSubmit}>
<label>Title</label>
<input type="text" name="title" value={input.title} onChange={handleChange} className="form-control" />
<p style={{ color: 'red' }}>{input.titleError}</p>
<label>Body</label>
<input type="text" name="body" value={input.body} onChange={handleChange} className="form-control" />
<p style={{ color: 'red' }}>{input.bodyError}</p>
<button>Submit</button>
</form>
</div>
);
}
export default TestComponent;
P.S. There will be much better ways to handle according to the scenario, but this may help you in some way.
EDIT:
Adding Radio button to select the user.
userId added to state
const [input, setInput] = useState({
title: '',
body: '',
titleError: '',
bodyError: '',
userId: '',
})
Radio select for users.
<div>
<input type="radio" name="userId" value="1" id="1"
checked={input.userId === "1"} onChange={handleChange}
/>
<label htmlFor="1">User 1</label>
</div>
<div>
<input type="radio" name="userId" value="2" id="2"
checked={input.userId === "2"} onChange={handleChange}
/>
<label htmlFor="2">User 2</label>
</div>
The same onChange handler will work for the radio select also. I see you use the response from useFetch to render the users. You can use same map logic to render this radio by setting the fields. Set the value and id attribute to user id from response and so on.

One immediate issue I found is a console error.
Production quality code from a Sr. level developer should not be doing this. I would expect to see errors in console if a bug was found or dealing with some edge case.
Warning: Failed prop type: Invalid prop buttonSelectedof typebooleansupplied toButton, expected string`.
in Button (at FormComponent.js:21)
in FormComponent (at App.js:8)
in div (at App.js:7)
in App (at src/index.js:9)
in StrictMode (at src/index.js:8)`
I found this in the console just browsing to the link you shared. There are other things to clean up but this is the most obvious thing I've found so far.

Related

Formik issue: Unable to edit text field in simple form in React app

I am unable to enter any text into a text input field within a plain html form that uses formik to handle changes to the field and to handle submit.
See the issue in action here:
https://formik-plain-form-issue.netlify.app/
I have encountered this issue while working on an app that uses Formik in combination with Redux, Bootstrap and Reactstrap, so I thought the issue may be related to these other libraries. However, a simplified version with a plain form and no state management is also showing a similar behaviour.
Here I am providing the code for the simplified version.
PlainForm component code:
// This is a React component
import { useFormik } from 'formik';
import './PlainForm.css';
const PlainForm = () => {
const formik = useFormik({
initialValues: {
name: '',
},
onSubmit: values => {
alert(`Plain form submitted with name: ${values.name}`);
},
});
return (
<div className='plain-form-container'>
<h1>Plain Form</h1>
<form
className='baseForm'
onSubmit={formik.handleSubmit}
noValidate
>
<label htmlFor='plain-form-name'>Name:</label>
<input
type='text'
id='plain-form-name'
className='nameField'
placeholder='Enter your name here'
value={formik.values.name}
onChange={formik.handleChange}
/>
<button type='submit'>Submit</button>
</form>
</div>
);
};
export default PlainForm;
You may see the full code for the test app here:
https://github.com/freenrg/Formik-Plain-Form-Issue
As pointed out by #shadow-lad in the comments, Formik needs the form field to have id and name matching the key of the property defined for that field in initialValues.
See https://formik.org/docs/tutorial
If you look carefully at our new code, you’ll notice some patterns and symmetry forming.
We reuse the same exact change handler function handleChange for each
HTML input
We pass an id and name HTML attribute that matches the property we defined in initialValues
We access the field’s value
using the same name (email -> formik.values.email)
Therefore, the code should be:
// This is a React component
import { useFormik } from 'formik';
import './PlainForm.css';
const PlainForm = () => {
const formik = useFormik({
initialValues: {
name: '',
},
onSubmit: values => {
alert(`Plain form submitted with name: ${values.name}`);
},
});
return (
<div className='plain-form-container'>
<h1>Plain Form</h1>
<form
className='baseForm'
onSubmit={formik.handleSubmit}
noValidate
>
<label htmlFor='plain-form-name'>Name:</label>
<input
type='text'
id='name'
name='name'
className='nameField'
placeholder='Enter your name here'
value={formik.values.name}
onChange={formik.handleChange}
/>
<button type='submit'>Submit</button>
</form>
</div>
);
};
export default PlainForm;
I have confirmed this works.

How do you use react-hook-form with redux and typescript properly

After many days of trying to find a guide that would show me all of these things in one example I finally gave up and made something that works via brute force, but I know that this is the wrong way to do it. I don't know exactly why it's wrong but it cant be as complicated as I have made it out to be here. These are my requirements:
use Redux to maintain application state
use React Hook Form for forms
use Typescript
forms must have client side and server side validation ability
Here is what I have:
import * as React from "react";
import { useForm } from "react-hook-form";
import { ErrorMessage } from '#hookform/error-message';
import { connect } from "react-redux";
import { MainMenu } from "./../components/MainMenu";
import { userSignupAction } from '../actions/authenticateActions';
interface FormInputs {
singleErrorInput: string;
userName: string;
password: string;
email: string;
firstName: string;
lastName: string;
}
export function Signup(props: any) {
const {
register,
formState: { errors },
setError,
handleSubmit,
clearErrors
} = useForm<FormInputs>();
const onSubmit = handleSubmit(async (data: FormInputs) => {
props.dispatch(userSignupAction(data));
});
if (props.response.signup.userName) {
if (!errors.userName) {
console.log('set username error')
setError('userName', {
type: "server",
message: props.response.signup.userName[0],
});
}
}
if (props.response.signup.email) {
if (!errors.email) {
setError('email', {
type: "server",
message: props.response.signup.email[0],
});
}
}
if (props.response.signup.password) {
if (!errors.password) {
setError('password', {
type: "server",
message: props.response.signup.password[0],
});
}
}
return (
<div>
<MainMenu role="anonymous"/>
<div className="center70">
<h2>Signup</h2>
<form onSubmit={onSubmit}>
<div>
<label>Username</label>
<input {...register("userName", { required: "Username is required"})}
onClick={() => {
console.log('clear the error');
props.response.signup.userName = false
clearErrors('userName');
}} />
{ errors.userName && <ErrorMessage errors={errors} name="userName" />}
</div>
<div>
<label>First Name</label>
<input {...register("firstName")} />
</div>
<div>
<label>Last Name</label>
<input {...register("lastName")} />
</div>
<div>
<label>Email</label>
<input {...register("email", { required: "Email is required"})} />
<ErrorMessage errors={errors} name="email" />
</div>
<div>
<label>Password</label>
<input {...register("password", { required: "Password is required"})} />
<ErrorMessage errors={errors} name="password" />
</div>
<input type="submit" />
</form>
</div>
</div>
);
}
const mapStateToProps = (response: any) => ({
response
});
export default connect(mapStateToProps)(Signup);
Note, this is not me trying to get an answer for my job, this is just me trying to learn this technology correctly. This code is all my code and not part of any proprietary application (clearly as it is not good)
Please help
More info...
My first challenge here was in trying to get a server side validation failure to show up on the front end. The way I tried to do this initially was by formatting the response as a json object exactly the way the error object is supposed to look in react-hook-forms, like so...
{
"userName": ["User 'jimbob' already exists"],
"email": ["User with email address 'jimbob#gmail.com' already exists"],
"password": ["Password must be at least 6 characters"]
}
At first I was expecting this response format to magically populate the error but it did not so this is why I had to add the three clauses to check the props value. Initially this caused an infinite loop so I had to add the second check to see if errors.fieldName was not truthy and only setError in those cases (great! I thought)
But then the next problem was, what happens when you get a server-side validation error but then the user goes back to fix it. Well in my opinion this should immediately clear the error the moment the user clicks on the field. Well this wasn't happening because even though the clearErrors function did it's job, the props check just immediately undid it so i had to add the extra line to set the field in props to false. yay! now it works, but at what cost?
This code all technically works now, but man is this a wordy piece of code for such a simple form. I can't believe that this is the right way to do things, it shouldn't take 100+ lines of code to make a simple 5 element form.
Your existing flow is currently as follows. Submit form -> setResponse -> re-render -> read response -> set errors.
A couple things to note.
You should not be using a client side validation tool (ReactHookForm) for server side validation/errors
Do not setError within the render method of the component
The async wrapper around dispatch is redundant
Re evaluate your requirements, because they aren't sensible.
A better flow would be either having your own redux middleware or utilise redux thunk. Change the flow to be:
Submit -> Check for errors -> setErrors via callback -> dispatch response -> set and display response
If you are creating react app with the help of react-redux library, there are built-in hooks for,
Get the data from the redux state - useSelector()
And dispatch actions to update the redux state - useDispatch()
Usage of useSelector() :-
So, you don't need to use following code to map redux state to props.
const mapStateToProps = (response:any) => ({
response
});
Simply, you should import useSelector() from react-redux as follows.
import {useSelector} from 'react-redux';
Then you can get whatever data from the redux state to your component.
const user = useSelector(state => state.user);
Usage of useDispatch() :-
You can use useDispatch() instead of using props to get dispatch(). This hook returns a reference to the dispatch function from the Redux store. You may use it to dispatch actions as needed.
import {useSelector, useDispatch} from 'react-redux';
const dispatch = useDispatch();
You can use dispatch reference wherever you want to dispatch a action, for example in your code instead of using following code,
const onSubmit = handleSubmit(async (data: FormInputs) => {
props.dispatch(userSignupAction(data));
});
you can use dispatch reference that we created as follows.
const onSubmit = handleSubmit(async (data: FormInputs) => {
dispatch(userSignupAction(data));
});
I took all the advice from the people who commented here and created the following which is much nicer (but could probably still be optimized a bit)
import React, { useState } from 'react';
import { useForm } from "react-hook-form";
import { ErrorMessage } from '#hookform/error-message';
import { useSelector, useDispatch } from 'react-redux';
import { MainMenu } from "./../components/MainMenu";
import { userSignupAction } from '../actions/authenticateActions';
interface FormInputs {
singleErrorInput: string;
userName: string;
password: string;
email: string;
firstName: string;
lastName: string;
}
export function Signup(props: any) {
const {
register,
formState: { errors },
handleSubmit
} = useForm<FormInputs>();
const response = useSelector(state => state.signup);
const dispatch = useDispatch();
const onSubmit = handleSubmit(async (data: FormInputs) => {
dispatch(userSignupAction(data));
});
const [updateCount, forceUpdate] = useState(0);
const clearError = (field) => {
response[field] = false;
forceUpdate(updateCount + 1);
}
return (
<div>
<MainMenu role="anonymous"/>
<div className="center70">
<h2>Signup</h2>
<form onSubmit={onSubmit}>
<div>
<label>Username</label>
<input {...register("userName", { required: "Username is required"})}
onClick={() => clearError('userName')}/>
<ErrorMessage errors={errors} name="userName" />
{ response.userName && <span>{ response.userName[0] }</span>}
</div>
<div>
<label>First Name</label>
<input {...register("firstName")} />
</div>
<div>
<label>Last Name</label>
<input {...register("lastName")} />
</div>
<div>
<label>Email</label>
<input {...register("email", { required: "Email is required"})}
onClick={() => clearError('email')}/>
<ErrorMessage errors={errors} name="email" />
{ response.email && <span>{ response.email[0] }</span>}
</div>
<div>
<label>Password</label>
<input {...register("password", { required: "Password is required"})}
onClick={() => clearError('password')}/>
<ErrorMessage errors={errors} name="password" />
{ response.password && <span>{ response.password[0] }</span>}
</div>
<input type="submit" />
</form>
</div>
</div>
);
}
export default Signup;
Notes: What I have above works and is much better than what I had before but there were still issues.
Issue #1: I have to have two separate elements which are conditionally in the DOM, one for client-side and the other for server-side errors. This annoys me, so I may make my own abstraction of both of these and put them into my own custom element in the future.
Issue #2: I figured out the problem that I was having (in reference to my comment on Dasun's answer) but it bother's me why this happened this way. What I had originally was something like this:
<ErrorMessage errors={errors} name="userName" />
{ props.response.submit.userName && <span>{ props.response.submit.userName[0] }</span>}
This code blew up because once I removed the connect call I no longer had props.response which makes sense, however what made this especially annoying was that the error did not reference the actual line of code that blew up, rather it referenced the line above that, and the error specifically mentioned the "errors" value as being undefined when in fact that was not the case.
Issue #3: This is much better, but it's still very wordy. It would be nice if someone made a form management module which was pre-made to handle server side errors, honestly it seems ridiculous that this one does not. I can't imaging any website which would only ever have client side errors.

Can't type text in my input fields in my form (Utilizing a React custom hook for input handling)

Ok, I am creating a fairly large form in React (only showing three of the fields here), and thus want to utilize a custom hook for the handling.
I found an article explaining a way to do this, however, when I try to type text in my input fields they don't get filled. My console.log of the e.target values it looks like the field gets reset after each keystroke. What do I miss? Cheers
I tried to simplify my code, and hope it makes sense:
import React, { useState } from "react";
//various other imports not relevant for this issue
const NetworkConfig = () => {
//Custom Hook inserted here for easy overview. Normally imported from external file
function useFormFields(initialState) {
const [fields, setValues] = useState(initialState);
return [
fields,
(e) => {
setValues({
...fields,
[e.target.id]: e.target.value,
});
},
];
}
const [fields, handleFieldChange] = useFormFields({
apnValue: "",
apnUsernameValue: "",
apnUserPwdValue: "",
});
// I omitted the submit button and its functionality in this post,
// to keep my problem clear
// The TextField component basicaly just adds some functionality not
// relevant to this problem. It is tested in other scenarios so in this
// case it basically just works as a normal HTML input[type="text"] field
return (
<div>
<div className="network-config-modal" id="network-config">
<div>
<div>
<h2>Network Config</h2>
</div>
<div className="network-config-row">
<div className="network-config-col">
<h3>Cellular Settings</h3>
<section className="network-config-section">
<TextField
value={fields.apnValue}
onChange={handleFieldChange}
label="APN"
outerLabel={true}
light={true}
type="text"
name="apn"
id="apn"
/>
<TextField
onChange={handleFieldChange}
value={fields.apnUsernameValue}
label="APN Username"
optional={true}
outerLabel={true}
light={true}
name="apn-username"
id="apn-username"
/>
<TextField
onChange={handleFieldChange}
value={fields.apnUserPwdValue}
label="APN Password"
optional={true}
outerLabel={true}
light={true}
name="apn-password"
id="apn-pwd"
/>
</section>
</div>
</div>
</div>
</div>
</div>
);
};
export default NetworkConfig;

A single onChange listener on a <form> tag

I was just playing a bit with a more generic way of dealing with form data, and figured that setting a single onChange listener on the wrapping form tag should work for all changes to input fields.
And indeed, it does - no surprise there. Events get called, I know what changed by inspecting event.target.name and can update state accordingly. Fully as expected.
However, React doesn't seem to like it and spams the well known "You provided a value prop to a form field without an onChange handler" console warning.
Would there be any other reason for not doing this, apart from the console warning? It seems to eliminate a lot of duplication React otherwise gets criticised about.
class App extends Component {
state = {
name: 'Default Name',
number: 12,
}
handleChange = (event) => {
this.setState({
[event.target.name]: event.target.value,
})
}
render() {
const { crashLogo } = this.props;
return (
<div className="App">
<form onChange={this.handleChange}>
<input type="text" name="name" value={this.state.name} />
<input type="number" name="number" value={this.state.number} />
</form>
</div>
);
}
}
Just for clarity: I'm not asking for alternative solutions, I know I can set the same change listener directly on every input, use redux-form, own wrapper components with context magic and so on...

Best Practice For Reading Form Data in React

I'm trying to do something in React that would be very simple in any other framework: I want to collect a bunch of values from a form.
Previously I did this sort of thing with a Backbone View, and it was very simple:
readFormValues: function() {
this.data.foo = this.$('[name="foo"]').val();
this.data.bar = this.$('[name="bar"]:checked').val();
});
But in React I can't seem to find an easy way to do that. It seems my only options are to ...
NOTE: Apologies for the formatting: code blocks and lists don't play well together :-(
Completely bypass React and use the jQuery + e.target to access the form:
handleSubmit: function(e) {
var $form = $(e.target).parents('form:first');
this.data.foo = $form.find('[name="foo"]);
},
render: function() {
return <form onSubmit="handleSubmit"><input name="foo"/></form>;
}
That works, and is simple, but it feels like I'm bypassing React and using JQuery when I should just be using React.
Provide callbacks to every form control:
handleFooClick: function(e) {
this.data.foo = event.target.value;
},
render: function() {
return <form><input name="foo" onChange="handleFooChange"/></form>;
}
This appears to be the React/Flux way, but it feels like a crazy amount of unnecessary work. In my Backbone example I needed just one line per form control, but with this approach every last control I build has to have its own onChange handler (and I have to hook that handler up to every element as I render it).
EDIT: One more disadvantage of this approach is that inside the callbacks this.props and this.state won't point to my form control's props/state (it will point to the input's props/state). This means that not only do I have to write a handler per input AND add that callback to every input as I render, but I also have to pass in my data object to every input!
Use refs:
handleSubmit: function(e) {
this.state.data.foo = this.refs.foo.value;
},
render: function() {
return <form><input ref="foo"/></form>;
}
This seems like a more sane solution, as I only need to add a "ref" attribute to every form control, and then I can read the data as easily as I could in Backbone. However, all the React documentation suggests that using refs that way is wrong (all of the examples using refs involve sending signals to the controls, eg. "focus on this input", not on reading data out of the controls).
I feel like there must be a "React-ive" way to access my form data that isn't needlessly complex, but I'm not seeing it because I don't understand React well enough. If any React expert could explain what I'm missing I would greatly appreciate it.
First, jQuery is an unnecessary dependency and it's not the cleanest option so let's rule it out.
Next, refs have issues with flexibility. See this answer for details. Let's rule refs out for all but the simplest cases.
That leaves option #2 - what Facebook calls controlled components. Controlled components are great because they cover all use cases (like validation on keyup). Although it's not much code, if you'd rather not add a simple change handler for each form element, you might use one change handler for all elements with the use of bind. Something like this:
handleChange: function(fieldName, e) {
console.log("field name", fieldName);
console.log("field value", e.target.value);
// Set state or use external state.
},
render: function() {
var someValue = this.state.someValue; // Or a prop is using external state
return (
<div>
<input
name="someName"
value={someValue}
onChange={this.handleChange.bind(this, "someName")} />
</div>
)
}
Or for an even cleaner way, see this answer.
You can use ReactLink to create a two-way binding between your react component and your state.
Described here: https://facebook.github.io/react/docs/two-way-binding-helpers.html
This is how I handle all fields in a form.
var My_Field=React.createClass({
_onChange: function(evt) {
var e=this.props.parent_form;
if (e) {
e.setState({email: evt.target.value});
}
},
render: function() {
return (
<input type="text" name={this.props.name} placeholder={this.props.label} onChange={this._onChange}/>
);
}
});
var My_Form=React.createClass({
getInitialState: function() {
return {
email: "",
};
},
_onSubmit: function(evt) {
evt.preventDefault();
alert(this.state.email);
},
render: function() {
return (
<form onSubmit={this._onSubmit}>
<My_Field name="email" label="Email" parent_form={this}/>
<input type="submit" value="Submit"/>
</form>
);
}
});
For a smaller project I have been using a single onChange call back for all inputs - something like this...
HandleClick(event) {
let values = this.state.values;
values[event.target.name] = event.target.value;
this.setState({values});
}
This requires that you name your inputs the same as you name their state property but I quite like that. Then you give the value stored in state to the value attribute of your input and you're all set - all your form state stored in one place with a single handler function.
Of course there are more scalable ways - I was just reading about a framework for react called formsy that looked interesting. Here's a tutorial:
http://christianalfoni.github.io/javascript/2014/10/22/nailing-that-validation-with-reactjs.html
Hope that helps
Dan
You can read form data using only one function.
class SignUp extends Component {
constructor(){
super();
this.handleLogin = this.handleLogin.bind(this);
}
handleLogin(e){
e.preventDefault();
const formData = {};
for(const field in this.refs){
formData[field] = this.refs[field].value;
}
console.log('-->', formData);
}
render(){
return (
<form onSubmit={this.handleLogin} className="form-horizontal">
<div className="form-group text-left">
<label className="control-label col-sm-2">Name:</label>
<div className="col-sm-10">
<input ref="name" type="text" className="form-control" name="name" placeholder="Enter name" />
</div>
</div>
<div className="form-group text-left">
<label className="control-label col-sm-2">Email:</label>
<div className="col-sm-10">
<input ref="email" type="email" className="form-control" name="email" placeholder="Enter email" />
</div>
</div>
<div className="form-group text-left">
<label className="control-label col-sm-2">Password:</label>
<div className="col-sm-10">
<input ref="password" type="password" className="form-control" name="password" placeholder="Enter password" />
</div>
</div>
<div className="form-group text-left">
<div className="col-sm-offset-2 col-sm-10">
<button type="submit" className="btn btn-primary btn-block">Signup</button>
</div>
</div>
</form>
)
} }export default SignUp;
The quickest and easiest way, using React's useState():
const Form = () => {
const [fullName, setFullName] = React.useState("");
const [is18, setOver18] = React.useState(false);
return (
<form>
<input
type="text"
name="fullName"
value={fullName}
onChange={event => setFullName(event.target.value)}
/>
<input
type="checkbox"
name="over18"
checked={is18}
onChange={() => setOver18(!is18)}
/>
</form>
);
};

Resources