I have a reusable radio button that I'm using throughout my application - a form.
I want to store the form data in session storage so users can review their answers before submitting and because I will send the data to myself via EmailJS.
How should I manage state - should I define state in the radio button component or should I define state in each of the components where the radio button is used?
Reusable Radio Button Component
import styled from "styled-components"
function RadioButton({id, value, name, children}) {
return (<>
<SelectionContainer>
<Input type='radio' id={id} value={value} name={name}/>
<Label htmlForfor={id}>
{children}
</Label>
</SelectionContainer>
</>)
}
const Input = styled.input`
margin-right: 1rem;
height: 1.1rem;
width: 1.1rem;
accent-color: grey;
`;
const Label = styled.label`
color: white;
`;
const SelectionContainer = styled.div`
display: flex;
align-items: center;
justify-content: flex-start;
width: 80%;
height: 5rem;
`;
export default RadioButton
Example Component That Uses Radio Button
import React from 'react'
import styled from 'styled-components'
import QuestionText from '../utils/Question';
import RadioButton from '../utils/RadioButton';
import { useState } from 'react';
function BackgroundInfo() {
return (<>
<QuestionText>Do you have content ready for your site?</QuestionText>
<RadioButton id='yes-content' value='Yes' name='user_contentReady'>
Yes, I have content ready.
</RadioButton>
<RadioButton id='no-content' value='No' name='user_contentReady'>
Not yet. I'm still working on it.
</RadioButton>
<QuestionText>Is your company legally registered?</QuestionText>
<RadioButton id='yes-registered' value='Yes' name='user_companyRegistered' >
Yes.
</RadioButton>
<RadioButton id='no-registered' value='No' name='user_companyRegistered'>
No.
</RadioButton>
<RadioButton id='not-yet' value='Not yet' name='user_companyRegistered'>
I'm in the process of registering it.
</RadioButton>
</>
)
}
export default BackgroundInfo
You can use a custom hook to manage the state of the radio inputs and pass it as a prop to the reusable component. The custom hook can use the useState
and useEffect
hooks to store and update the selected value, and also provide a handleChange
function to handle the input change event.
For example:
// RadioInput.js
import React from "react";
function RadioInput({ value, checked, label, ...rest }) {
return (
<label>
<input value={value} checked={checked} {...rest} />
{label}
</label>
);
}
export default RadioInput;
// useRadio.js
import { useState, useEffect } from "react";
const useRadio = (name, defaultValue) => {
const [value, setValue] = useState(defaultValue);
useEffect(() => {
const storedValue = sessionStorage.getItem(name);
setValue(storedValue || defaultValue);
}, [name, defaultValue]);
const handleChange = (event) => {
const newValue = event.target.value;
setValue(newValue);
sessionStorage.setItem(name, newValue);
};
const inputProps = {
name,
type: "radio",
onChange: handleChange,
};
return [value, inputProps];
};
export default useRadio;
// App.js
import React from "react";
import RadioInput from "./components/RadioInput";
import useRadio from "./hooks/useRadio";
const options = [
{ label: "Option 1", value: "option1" },
{ label: "Option 2", value: "option2" },
];
function App() {
const [value, inputProps] = useRadio("radio", "option1");
return (
<div>
{options.map((option) => (
<RadioInput
key={option.value}
value={option.value}
checked={value === option.value}
label={option.label}
{...inputProps}
/>
))}
</div>
);
}
export default App;