1

Scenario: In the process of building eCommerce software using react. For the product detail page, some products will have options (size, color) and some will not. The ones that do i iterate through the options and dynamically create select elements(code below):

<div className='mt-4'>
{item.options.length > 0
? item.options.map((option) => (
 <div>
   <p>{option.name}</p>
   <select className='rounded-md border-2 w-32 h-12' onChange={handleAddOptions}>
      {option.values.map((val) => (
        <option value={val}>{val}</option>
      ))}
   </select>
 </div>
 ))
  : ''}
</div>

Here is the handleAddOptions function:

const handleAddOptions = (e) => {
   setOptions([...options, e.target.value]);
};

Now this works but not the way I want it to. It just keeps adding the options to one big array. I need the array to only be one option from each selection, no matter if the user changes multiple times.

Example:

Options are Size and Color (There could always be more though)

User picks small and blue then switches size to medium. My code would create an options array like this: [small, blue, medium] which would hold two size selections(can't have that).

EDIT: The final options array should only ever have one option from each selection. so in this case, if the user selects size many times the final array should only hold the most recent size option.

0

1 Answer 1

1

Change your handler to only add new options, for example:

const handleAddOptions = (e) => {
   const option = e.target.value;

   setOptions(options => 
      options.inculdes(option) 
         ? options 
         : [...options, option]
   );
}

Update

If you have multiple selections of options, something like this :

import { useState } from "react";

const item = {
  options: [
    {
      name: "Size",
      values: ["sm", "md", "lg", "xl"]
    },
    {
      name: "Color",
      values: ["red", "blue", "green", "white", "black"]
    }
  ]
};

export default function App() {
  const [selectedOptions, setSelectedOptions] = useState(() => ({}));

  const handleAddOptions = (e) => {
    const optionName = e.target.getAttribute("data-option");
    const optionValue = e.target.value;

    setSelectedOptions((options) => ({
      ...options,
      [optionName]: optionValue
    }));
  };

  return (
    <div className="App">
      <h1>Option selection</h1>

      <div className="mt-4">
        {item.options.length > 0
          ? item.options.map((option) => (
              <div key={option.name}>
                <p>{option.name}</p>
                <select
                  className="rounded-md border-2 w-32 h-12"
                  data-option={option.name}
                  onChange={handleAddOptions}
                >
                  {option.values.map((value) => (
                    <option key={value} value={value}>
                      {value}
                    </option>
                  ))}
                </select>
              </div>
            ))
          : ""}
      </div>

      <h3>Selected Options</h3>
      {item.options.length > 0
        ? item.options.map((option) => (
            <div key={option.name}>
              {option.name} : {selectedOptions[option.name]}
            </div>
          ))
        : ""}
    </div>
  );
}

Source available here.

Sign up to request clarification or add additional context in comments.

3 Comments

This kind of helps! But not quite what I need. The options array should only ever be the length of however many selections there are. So if it's size and color, the array should only ever have one size option and one color option.
@stinny then ask the right question in order to have the right answer... :) this precision was not part of the original question.
It says the array should only be one option from each selection, I will make an edit for clarity though. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.