Home > Mobile >  React State For Many Items
React State For Many Items

Time:04-26

Users select one of four options for 70 questions. The four options never change but I need to know which was selected for each question. The code below works but I am trying to determine if I should copy this code 70 times or if there is a better way? Thanks!


const [selected, setSelected] = useState({
  option1: {
    title: "I can think of where this has lead me",
    selected: false,
  },
  option2: {
    title: "I can think of how this has changed me",
    selected: false,
  },
  option3: {
    title: "I can think of how I overcame this",
    selected: false,
  },
  option4: {
    title: "This has an interesting backstory",
    selected: false,
  },
});

const selectingOption1 = () => {

  setSelected({
    ...selected,
    option1:{selected: true,
      title: "I can think of where this has lead me" }
  })

}

Example of displaying question:

<Card onClick={props.selectingOption1}  className={classes.itemCard}>
  <img className={classes.iconImg} src='/item1.png' />
  <p> I can think of where this has lead me</p>
</Card>

CodePudding user response:

I would create a component for options and would import it inside this component. Then You can give options with props. Inside the new component you would need just one state for options part

const [selected, setSelected] = useState({ title: "", selected: false })

CodePudding user response:

No, you don't need to copy the same code 70 times.

You can get it by defining the array of 70 questions with options.

Here are the steps you can refer to.

You can define the question's data structure with 4 options.

Note that question object has id property as a unique key to identify the question.

   
      {
        id: 1,
        title: 'Question 1',
        options: {
          option1: {
            title: "I can think of where this has lead me",
            selected: false,
          },
          option2: {
            title: "I can think of where this has lead me",
            selected: false,
          },

        }
      }
   

Then you can define a state variable for 70 questions and set it in useEffect or wherever. Maybe you can get it from props or define it as a constant array.

const [questions, setQuestions] = useState<any>([]);
useEffect(() => {
    // some API call to get questions
    // We assume like the following:
    const questions = [
      {
        id: 1,
        title: 'Question 1',
        options: {
          option1: {
            title: "I can think of where this has lead me",
            selected: false,
          },
          option2: {
            title: "I can think of where this has lead me",
            selected: false,
          },
        }
      }
    ];
    setQuestions(questions);
}, [])

Define a function to select an option with 2 parameters. The first parameter is question ID and the second is option id.

  const selectOption = (questionId, optionKey) => {
    setQuestions((prev) => {
      const newData = [...prev];
      const q = newData.find(x => x.id === questionId);
      if (q) {
        q.options = {...q.options, [optionKey]: true};
      }
      return newData;
    });
  }

Render method

I basically made a render function that could be broken down more by you.

You may make Question component and Options to render 4 options.

  return (
    <>
      {questions.map((question) => (
        <Card key={question.id} question={question}  className={classes.itemCard}>
          <img className={classes.iconImg} src='/item1.png' />
          <p> {question.title}</p>
          {Object.keys(question.options).map((optionKey) => (
            <div key={optionKey} onClick={selectOption(question.id, optionKey)}>{question.options[optionKey].title}</div>
            ))}
        </Card>
      ))}
    </>
  )
  • Related