React Inputs
Handling inputs in React is similar to how you'd handle them in HTML, except we can take advantage of React hooks to manage the state of the input inside our main React App component. This is known as a controlled component because the state is controlled by our code with React hooks.
We'll be using the standard HTML <input>
tag, React hooks and styled-components for easy styling and stateful functionality.
Controlled vs Uncontrolled Input Examples
We're demonstrating both a text input controlled by React, and an uncontrolled component controlled by the native browser DOM. Native HTML forms will automatically store the value of the input inside the DOM. So, if you don't want to keep track of state with React, you can just handle the submit event with native browser functionality, and capture that inside a React callback. In this example, we handle this in submitForm
. This is not really a typical approach in React apps because most of the time you will want the state variable inside your app, for example to perform real-time validation.
React Text Input props
Note that when discussing these input "props", we're referencing the standard HTML attributes, and so as with all React props, they are the same as the HTML attributes except for callback functions like onChange
which
are camelCase. Feel free to reference HTML documentation for other standard attributes that can be set through props.
React input value prop
The value
prop is what determines the input's value. For text inputs, this is simply the current text value of the input, making it simple to understand when writing stateful logic. For checkboxes and radio buttons, it's the checked
prop, as we describe in following lessons.
React input onChange prop
The onChange prop is a function that responds when the user interacts with the input. The browser tells us that a new value has been detected. However, we have not saved this value state anywhere in our application, so that's where we use hooks to create a "custom React hook", which is really just a function that returns the dynamic value/onChange props.
Using React hooks with inputs
So, the key is that we use the useState
hook inside a helper method which we call useInput
. This itself now becomes a "custom hook".
Because all inputs share the same value
and onChange
props, this stateful functionality becomes reusable for any future inputs we want to create in our app.
We declare the onChange
callback inside this hook, which uses the setValue
callback given to us from React hooks. As a reminder, value
and setValue
are just names we created, as the useState
hook doesn't require specific names for
these attributes. We added an optional defaultValue
argument we provide in case you would want to initialize the value
(from data from a server for example) inside the useState
call itself. So, now that we have our local input value
and
onChange
props, we return those and then use the ...spread
notation to place these props on our StyledInput.
import React, { useState } from "react"; import styled from "styled-components"; // Styling a regular HTML input const StyledInput = styled.input` display: block; margin: 20px 0px; font-size: 18px; padding: 8px; border: 1px solid lightblue; `; // Creating a custom hook function useInput(defaultValue = "") { const [value, setValue] = useState(defaultValue); function onChange(e) { setValue(e.target.value); } return { value, onChange, }; } export default function App() { // Using a fancy shared React hook to control input state const inputProps = useInput(); // Using native DOM form submission to store state function submitForm(event) { // Prevent the default event because it causes a page refresh event.preventDefault(); const data = new FormData(event.target); alert(data.get("myInput")); } return ( <div> <h1> React Input Examples </h1> <h2> Controlled input </h2> <p> This input is <i> controlled </i> by React hooks{" "} </p> <StyledInput {...inputProps} placeholder="Type in here" /> <span>Value: {inputProps.value} </span> <h2> Uncontrolled input </h2> <p> This input's state is <i> not </i> controlled by React, it relies on native DOM form submissions. Submitting will parse the form values. </p> <form onSubmit={submitForm}> <label> Name: <StyledInput placeholder="Type in here" name="myInput" type="text" /> </label> <input type="submit" value="Submit" /> </form> </div> ); }