ui > Inputs
Guide To React Inputs - Text, Checkbox, Radio
In this guide we're going to do a functional overview of the types of input elements that you can create with React.
We'll be using the standard HTML <input>
tag, starting from the default text input, and then moving onto other input
types configured through the type
prop. We'll be using React hooks and styled-components for easy styling and stateful functionality.
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 Text Input Example with Hooks
import React, { useState } from 'react';import styled from 'styled-components';// Styling a regular HTML inputconst StyledInput = styled.input`display: block;margin: 20px 0px;border: 1px solid lightblue;`;// Creating a custom hookfunction useInput(defaultValue) {const [value, setValue] = useState(defaultValue);function onChange(e) {setValue(e.target.value);}return {value,onChange,};}// Usage in Appfunction App() {const inputProps = useInput();return (<div><StyledInput{...inputProps}placeholder="Type in here"/><span>Value: {inputProps.value} </span></div>);}
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 below.
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.
Using checkboxes and radio buttons with React
Checkboxes and radio buttons use the checked
property to determine their UI state (true or false),
with their value
being an arbitrary name for that selection. What can be confusing about this is that the checked
HTML
attribute here was intended to just set which checkbox/radio was set initially. The browser would keep track of
when the user checked/unchecked inputs, not updating the checked attribute, and then when the user submitted a form,
the browser would include the name/value props for the checked inputs automatically. We do things quite differently
in React, where we are required to set the checked
attribute, and watch for changes through onChange
, and then
keeping track of the state ourselves by examining e.target.checked
.
const checkboxesList = ['New Jersey','Maryland','Connecticut','Florida','Massachussets',];const getDefaultCheckboxes = () =>checkboxesList.map(checkbox => ({name: checkbox,checked: false,}));export function useCheckboxes(defaultCheckboxes) {const [checkboxes, setCheckboxes] = useState(defaultCheckboxes || getDefaultCheckboxes(),);function setCheckbox(index, checked) {const newCheckboxes = [...checkboxes];newCheckboxes[index].checked = checked;setCheckboxes(newCheckboxes);}return {setCheckbox,checkboxes,};}const Checkbox = styled.input`margin: 0px 10px 0px !important;cursor: pointer;`;const CheckboxLabel = styled.label`cursor: pointer;display: block;font-weight: normal;`;export function Checkboxes({ checkboxes, setCheckbox }) {return (<>{checkboxes.map((checkbox, i) => (<CheckboxLabel><Checkboxtype="checkbox"checked={checkbox.checked}onChange={e => {setCheckbox(i, e.target.checked);}}/>{checkbox.name}</CheckboxLabel>))}</>);}export function CheckboxRadioExample() {const checkboxes = useCheckboxes();return (<div><Checkboxes {...checkboxes} /><span>Value:{checkboxes.checkboxes.filter(t => t.checked).map(checkbox => checkbox.name).join(', ')}</span></div>);}
Checkbox Example with Hooks
Above you can see an example which initializes a list of checkboxes from a static list of US states. We map the list in getDefaultCheckboxes
to create our initial state object array, which gets initialized when our useCheckboxes
hook gets run at the beginning of our CheckboxRadioExample
render method. We then name the array properties [checkboxes, setCheckboxes]
as our state variable and setter.
From here, we have the custom hook return
the list of checkboxes
and a new callback setCheckbox
which we create within the scope of the hook. The callback
creates a copy of the current checkboxes
list and sets the checked
property of the passed index on the array. Then it sets the new array with the setCheckboxes
setter.
At this point we have fully scoped the state logic of our checkbox list in the useCheckboxes
hook. We're now free to use it in our app!
We render a list of CheckboxLabel
(a <label>
created by styled-components) and a <Checkbox type="checkbox">
(a styled.input
). The type
HTML attribute is
what makes this a checkbox. We also add an onChange
attribute here which we then access the e.target.checked
(current checkbox state) from the event handler.
When someone interacts with a checkbox by mouse OR keyboard actions, (try tabbing and hitting spacebar on a checkbox), the onChange
handler is fired,
and we call our hook to update the list of checkboxes. The cycle is complete.
🛈 React School creates templates and video courses for building beautiful apps with React. Download our free Material UI template.