2

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
greybeard
  • 2,249
  • 8
  • 30
  • 66

1 Answers1

2

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;
Pluto
  • 4,177
  • 1
  • 3
  • 25
  • Thank you! Reading through your solution, I think it will work and will experiment with implementing it today. As for storing the values in session storage, how would that factor into your solution? Would you suggest putting it the handleChange function? – Christoper Chamberlain Jul 10 '23 at 00:43
  • 1
    To use session storage in the custom hook, you can modify the useEffect and handleChange functions. I updated my answer for session storage. Please check it. – Pluto Jul 10 '23 at 01:08