Как получить доступ к имени элементов в React useState

#reactjs #react-hooks #use-state

#reactjs #реагирующие хуки #use-state

Вопрос:

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

Пока это мой код

 import React, { useState, useEffect } from "react";

import MattressUpgrade from "./CamperMods/MattressUpgrade";

const CamperModsContainer = () => {
  const [iconType, setIconType] = useState({
    mattressUpgrade: "",
  });

  const [show, setShow] = useState({
    mattressUpgrade: false,
  });

  useEffect(() => {
    setIconType({
      mattressUpgrade: "fas fa-plus-square",
    });
    setShow({
      mattressUpgrade: false,
    });
  }, []);

  let onClickHandler = (event) => {
    event.preventDefault();
    let payload = event.currentTarget;
    toggleShow(payload);
  };

  const toggleShow = (payload) => {
    debugger;
    if (payload.value === true) {
      setIconType.payload.id("fas fa-minus-square");
      setShow.payload.id(true);
    } else if (payload.value === false) {
      setIconType.payload.id("fas fa-plus-square");
      setShow.payload.id(false);
    }
  };

  return (
    <div>
      <h1>Camper Modifications</h1>
      <p>
        As much as we love the Wolf Pup (aka the amp;apos;Gray Ghostamp;apos;), there
        are some things that we tweaked...
      </p>
      <div className="flex-row">
        <h3>Mattress Upgrade</h3>
        <button
          type="button"
          id={show.mattressUpgrade.key}
          value={show.mattressUpgrade}
          className={iconType.mattressUpgrade}
          onClick={onClickHandler}
        ></button>
      </div>
      {show === true amp;amp; <MattressUpgrade />}
    </div>
  );
};

export default CamperModsContainer;
 

Проблема в том, что установка идентификатора в id={show.mattressUpgrade.key} значение не работает. Когда я нажимаю на отладчик, toggleShow я могу получить доступ payload.value и получить значение false . Но если я попытаюсь это сделать payload.id , это вернет пустую строку, и я не могу понять, почему.

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

1. Зачем кнопке вообще нужен an id ? Также чего вы ожидаете show.mattressUpgrade.key ? Я могу сказать вам, что здесь не так, но я не совсем понимаю, какова ваша цель в проблемном коде.

2. И почему вы устанавливаете такое состояние setIconType.payload.id ? useState возвращает функцию, вам просто нужно ее вызвать

3. В настоящее время в каждом из этих useStates есть только один элемент, mattresssUpgrade . Но это будет еще не все. Итак, я пытался выяснить, как я могу обновить только этот конкретный элемент useState. Например, если нажать » » рядом с обновлением матраса, я бы хотел обновить useMattress только состояние, а не каждый элемент, который может находиться в show useState.

Ответ №1:

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

Общее предложение состоит в том, чтобы стараться поддерживать согласованность типов данных, когда это возможно. Преобразование между строкой и логическим значением сложно отслеживать и отлаживать. Если вы в конечном итоге переключаетесь между более сложными типами данных (объектами и т. Д.), Это становится очень подверженным ошибкам.

Первая проблема заключается в том, что show.mattressUpgrade.key это не работает, и это никогда не будет работать. key доступен как свойство объекта show.mattressUpgrade , но show.mattressUpgrade не является объектом, его false . Вы можете развернуть и запустить приведенный ниже фрагмент, чтобы увидеть, что доступ к свойству приводит к false результату undefined , а назначение undefined в качестве входных id данных приводит к e.target.id пустой строке.

 const Example = () => {
  const test = false;
  console.log('test.property', test.property);
  
  const handleChange = (e) => {
    console.log(e.target.id)
  }
  
  return <input id={test.property} onChange={handleChange} />
}

ReactDOM.render(<Example />, document.getElementById('root')); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div> 

Я не могу сказать вам, как вы должны установить id для button ‘s в вашем коде, потому что в вашем примере есть только один, но именно поэтому id не работает.

Что касается состояния обновления динамически, setShow.payload.id это неправильный путь. setShow это функция, а не объект. Даже если бы это было так, вы бы не ссылались на него с помощью переменной payload.id , вы бы пытались получить доступ к буквальному вложенному свойству с именем «полезная нагрузка», а затем «идентификатор». Более того, id не ожидается, что это будет функция, но вы все равно вызываете ее как единое целое.

Для динамического доступа к свойствам объекта используется синтаксис массива ( ojb['property'] ). Тогда ваша функция будет выглядеть примерно так:

   const toggleShow = (payload) => {
    debugger;
    if (payload.value === true) {
      setIconType(prev => ({...prev, [payload.id]: "fas fa-minus-square"}));
      setShow(prev => ({...prev, [payload.id]: true}));
    } else if (payload.value === false) {
      setIconType(prev => ({...prev, [payload.id]: "fas fa-plus-square"}));
      setShow(prev => ({...prev, [payload.id]: false}));
    }
  };
 

Обратите внимание, что мы также используем функциональное обновление и распространение prev в новый объект, чтобы сохранить любые значения, которые явно не заменяются.

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

1. Итак, я предполагаю, что мой последующий вопрос будет заключаться в следующем: что мне следует исследовать, чтобы выяснить, как создать макет в стиле аккордеона с использованием реактивных крючков, который позволяет отображать одновременно более одного раздела? Я новичок в кодировании (очевидно) и изо всех сил пытаюсь найти примеры того, как это сделать с помощью синтаксиса hooks vs class.

2. Чем это отличается от компонента класса? Проблемы здесь на самом деле не относятся к функциональным компонентам, это общие недоразумения JavaScript, которые также могут вызвать проблемы в классе. К сожалению, у меня нет никаких рекомендаций и где найти примеры этой функциональности.