Переключатель с меткой в react js

#javascript #reactjs

#javascript #reactjs

Вопрос:

Всем привет!

Сегодня я пытаюсь создать выбираемый атрибут, например nike.com Air Force 1 страница товара в корзину

Моя проблема заключается в следующем: Захват-d-cran-2020-10-19-12-57-35. png

Я хочу выбрать один элемент и сохранить значение переключателя в состоянии.

Для этого я использую useRef :

 const getValueFromRadio = React.useRef(null)
  

Для вызова этих ссылок я использую onClick(myFunction) тег label

 <h1 className="text-center text-2xl">{product.name}</h1>
<div>
    <div className={'block my-3'}>
        {product.attribute !== undefined ? product.attribute.map((item, index) => <div className={'inline-block'} key={index}>
        <label onClick={labelOnclickHandler} className="cursor-pointer py-2 px-3 my-3 mx-2 border border-grey-500 hover:border-black h-3 rounded" htmlFor={item.id}>{item.value}</label>
        <input className="hidden" ref={getValueFromRadio} type="radio" id={item.id} value={item.value} name={'selectSize'}/>
              </div>)
         : null}
     </div>
</div>

// sorry for the piss of shit indentation.
  

Если у меня есть только один атрибут, ссылка получит S размер, а значение, которое я сохраняю в своем состоянии, равно S:

 const labelOnclickHandler = (e) => {
        const el = e.target.classList
        if (el.contains('border-grey-500')){ //toggling.
            el.remove('border-grey-500')
            el.add('border-black')
        } else {
            el.add('border-grey-500')
            el.remove('border-black')
        }
        setPrevElement(el) // get preview el for remove the border black.
        setSelectSize(getValueFromRadio.current.value) // state to cart.
}
  

Но если у меня есть несколько атрибутов, реакция или ссылки возвращают меня каждый раз, когда «M», и я не знаю, является ли это ошибкой или это не лучший способ сделать это.

Ответ №1:

Вы можете использовать htmlFor on <label> , а затем, когда вы нажимаете на эту метку, вы запускаете ввод, если htmlFor атрибут равен вводу ID .

Затем вы можете обработать изменение состояния с onChange помощью события RadioButton:

 <label htmlFor={item.id}>
   <input 
     id={item.id} 
     type='radio' 
     onChange={() => radioChangeHandler(item.id)}
   />
</label>
  

И затем:

 const radioChangeHandle = (id) => {
    setRadioState(id);
}
  

Таким образом, вы могли бы переключать свои классы по-другому, например:

 className={` ${ RadioState === item.id ? "border-black" : "border-grey-500" } cursor-pointer py-2 px-3`}
  

Комментарии:

1. хорошо, но с вашим кодом мне нужен новый функциональный компонент? Я не думаю, что они будут иметь одинаковое состояние?

2. Но я пытаюсь это сейчас, я вернусь к вам 😁

Ответ №2:

Другое решение — передать индекс выбранного элемента:

   const labelOnclickHandler = (e, index) => {
    const el = e.target.classList
    if (el.contains('border-grey-500')){ //toggling.
        el.remove('border-grey-500')
        el.add('border-black')
    } else {
        el.add('border-grey-500')
        el.remove('border-black')
    }
    setPrevElement(el) // get preview el for remove the border black.
    setSelectSize(product.attribute[index].value) // state to cart.
}
  

И вам не нужно использовать ссылку:

 <div>
        <div className={"block my-3"}>
          {product.attribute !== undefined
            ? product.attribute.map((item, index) => (
                <div className={"inline-block"} key={index}>
                  <label
                    onClick={(e)=> labelOnclickHandler(e, index)}
                    className="cursor-pointer py-2 px-3 my-3 mx-2 border border-grey-500 hover:border-black h-3 rounded"
                    htmlFor={item.id}
                  >
                    {item.value}
                  </label>
                  <input
                    className="hidden"
                    type="radio"
                    id={item.id}
                    value={item.value}
                    name={"selectSize"}
                  />
                </div>
              ))
            : null}
        </div>
      </div>
  

Я рекомендую вам избегать использования индекса в качестве значения ключа (key={index}). Больше информации здесь https://reactjs.org/docs/lists-and-keys.html

Может быть, вы можете использовать key={`product_attribute_${index}`}