React onClick, чтобы повлиять только на эту итерацию - PullRequest
1 голос
/ 15 апреля 2020

У меня есть страница, которая использует объект, который содержит списки в списках. У меня есть все компоненты, отображающие данные правильно, но я пытаюсь добавить кнопку переключения для каждого первичного элемента списка, чтобы вы могли показать / скрыть их дочерние списки. Ранее я делал что-то, что влияло бы на КАЖДЫЙ экземпляр компонента при нажатии, поэтому, когда вы нажимаете кнопку expand, это переключает дочерние списки КАЖДОГО первичного элемента.

Реакция является новой для меня, и я ' Я использую этот проект частично в качестве учебного пособия. Я считаю, что это связано с состоянием привязки к указанному c экземпляру компонента, но я не уверен, как и где это сделать.

Вот компонент:

const SummaryItem = props => {
  const summary = props.object;

  return(
    <div className="summary_item">
      {Object.entries(summary).map( item =>
        <div>
          Source: {item[0]} <br />
          Count: {item[1].count} <br />
          <button onClick={/*expand only this SummaryItemList component*/}>expand</button>
          <SummaryItemList list={item[1].items} />
        </div>)
      }
    </div>
  );
}

Ранее у меня был хук состояния, который выглядел так:

const [isExpanded, setIsExpanded] = useState(false);
const toggle = () => setIsExpanded(!isExpanded);

И в моей функции рендеринга кнопка имела функцию переключения в onClick: <button onClick={toggle}>expand</button>, и у меня было условное if(isExpanded) с двумя рендеринга, один с компонентом SummaryItemList, а другой без.

Есть ли лучший способ сделать это, кроме отображения объекта, и как мне связать состояние переключателя, чтобы влиять только на экземпляр, на который он должен влиять?

1 Ответ

2 голосов
/ 15 апреля 2020

Я думаю, что вы, возможно, забыли дать каждому элементу isExpanded, лучший способ сделать это - разделить ваши элементы и элементы на различные компоненты (в приведенном ниже примере это Список элементов и Элемент для элемента).

const { useState } = React;
const Item = ({ name, items }) => {
  const [isExpanded, setIsExpanded] = useState(false);
  const toggle = () => {
    setIsExpanded((s) => !s);
  };
  return (
    <li>
      {name}
      {items && (
        <React.Fragment>
          <button onClick={toggle}>
            {isExpanded ? '-' : '+'}
          </button>
          {isExpanded && <List data={items} />}
        </React.Fragment>
      )}
    </li>
  );
};

const List = ({ data }) => {
  return !data ? null : (
    <ul>
      {Object.entries(data).map(([key, { items }]) => (
        <Item key={key} items={items} name={key} />
      ))}
    </ul>
  );
};
const App = () => {
  const data = {
    A: {
      items: {
        AA1: { items: { AAA1: {}, AAA2: {} } },
        AA2: { items: { AAA: {} } },
      },
    },
  };
  return <List data={data} />;
};
ReactDOM.render(<App />, 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>
...