0

i have two product cards each have it's own category like color,size,etc and each have add to cart button. im using useRef() hook to get the selected category by user. and console it, when i click add to cart button.the problem is im only getting the second product category selected by the user whenever i press both buttons. please do check the code below.feel free to ask for any clarification.

import "./Card.css";
import { useRef } from "react";

function Card() {
  const colorRef = useRef();
  const quantityRef = useRef();
  const sizeRef = useRef();

  const submitHandler = (event) => {
    event.preventDefault();

    const selectedColor = colorRef.current.value;
    const selectedQuantity = quantityRef.current.value;
    const selectedSize = sizeRef.current.value;

    const selectedData = {
      color: selectedColor,
      quantity: selectedQuantity,
      size: selectedSize
    };
    console.log(selectedData);
  };

  return (
    <div className="main-container">
      <div className="container">
        <div className="image-container">
          <img
            src="https://images.pexels.com/photos/9558601/pexels-photo-9558601.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
            alt=""
          />
        </div>
        <h2> T-Shirt </h2>
      </div>
      <form className="form-conatiner" onSubmit={submitHandler}>
        <div className="selectors">
          <p>Solid Round Neck T-shirt</p>
          <select id="color" ref={colorRef} name="color" required>
            <option>Color</option>
            <option value="black">Black</option>
            <option value="green">Green</option>
            <option value="orange">Orange</option>
          </select>

          <select ref={quantityRef} name="qantity" required>
            <option>Quantity</option>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
          </select>

          <select ref={sizeRef} name="size" required>
            <option>Size</option>
            <option value="medium">Medium</option>
            <option value="large">Large</option>
            <option value="small">Small</option>
          </select>
          <div>
            <button>Add to Cart</button>
          </div>
        </div>
      </form>
      <div className="container">
        <div className="image-container">
          <img
            src="https://images.pexels.com/photos/440320/pexels-photo-440320.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
            alt=""
          />
        </div>
        <h2> i-Watch </h2>
      </div>
      <div className="form-conatiner">
        <div className="selectors">
          <p>Dizo watch with amlod </p>
          <select id="2" ref={colorRef} name="color" required>
            <option>Brand</option>
            <option value="Apple">Apple</option>
            <option value="Samsung">Samsung</option>
            <option value="Pixel">Pixel</option>
          </select>

          <select ref={quantityRef} name="qantity" required>
            <option>Quantity</option>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
          </select>

          <select ref={sizeRef} name="size" required>
            <option>size </option>
            <option value="29mm">29mm</option>
            <option value="34mm">34mm</option>
            <option value="42mm">42mm</option>
          </select>
          <div>
            <button onClick={submitHandler}>Add to Cart</button>
          </div>
        </div>
      </div>
    </div>
  );
}
export default Card;

Anandhu A
  • 9
  • 3
  • Does this answer your question? [How can I use multiple refs for an array of elements with hooks?](https://stackoverflow.com/questions/54633690/how-can-i-use-multiple-refs-for-an-array-of-elements-with-hooks) – Jatin Parmar Oct 13 '22 at 17:50

2 Answers2

0

That is an expected behaviour. The ref is going to be assigned to the first element and then to the second one. That is why you're getting always the last. Second one, you're wrapping only one element with the form tag.

For this you should use useState hook and the onChange for the inputs. Let's say:

function Card() {
  const [firstElement, setFirstElement] = useState({})
  const [secondElement, setSecondElement] = useState({})
  
  const handleFirstElementChange = (key, event) => {
    setFirstElement((oldState) => ({ ...oldState, [key]: event.target.value }))
  }
  
  const submitHandler = (event) => {
    event.preventDefault();

    console.log(firstElement, secondElement);
  };
  
  return <>
    <h2>T-shirt</h2>
    <select id="color" required onChange={(event) => handleFirstElementChange('color', event)>
      <option>Pick a color</option>
      <option value="black">Black</option>
      <option value="white">White</option>
      <option value="red">Ref</option>
    </select>
  </>
}
Eric
  • 1
  • 1
  • This is helpful and it works perfectly. thanks, But i actually wanted it to be done with useRef itself. instead you used useState. can you help me to do this with useRef ? – Anandhu A Oct 12 '22 at 17:42
0

You are using same ref with different elements,so it will have reference to last element,to which it is passed, That's why you always get second product's references You should try using ref array like this

const colorRef = useRef([]);
const quantityRef = useRef([]);
const sizeRef = useRef([]);

and pass it this way (here is for one product)

      <select id="color" ref={(el)=>{colorRef.current.push(el)}} name="color" required>
        <option>Color</option>
        <option value="black">Black</option>
        <option value="green">Green</option>
        <option value="orange">Orange</option>
      </select>

      <select ref={(el)=>{quantityRef.current.push(el)}}  name="qantity" required>
        <option>Quantity</option>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
      </select>

      <select ref={(el)=>{sizeRef.current.push(el)}}  name="size" required>
        <option>Size</option>
        <option value="medium">Medium</option>
        <option value="large">Large</option>
        <option value="small">Small</option>
      </select>

and then use it like this way in you submit handler

const submitHandler = (event) => { event.preventDefault();

const selectedColor1 = colorRef.current[0].value;
const selectedColor2 = colorRef.current[1].value;

const selectedQuantity1 = quantityRef.current[0].value;
const selectedQuantity2 = quantityRef.current[1].value;

const selectedSize1 = sizeRef.current[0].value;
const selectedSize2 = sizeRef.current[1].value;

const selectedData1 = {
  color: selectedColor1,
  quantity: selectedQuantity1,
  size: selectedSize1
};
const selectedData2 = {
  color: selectedColor2,
  quantity: selectedQuantity2,
  size: selectedSize2
};
console.log(selectedData1);
console.log(selectedData2);
 };

A working codesandbox is here.

A good and sort read Here. Hope this will help.

Jatin Parmar
  • 2,759
  • 5
  • 20
  • 31