【问题标题】:React onClick to affect only this iteration反应 onClick 只影响这个迭代
【发布时间】:2020-04-15 17:32:56
【问题描述】:

我有一个页面使用一个包含列表中的列表的对象。我的所有组件都正确显示了数据,但我正在尝试为每个主要列表项添加一个切换按钮,以便您可以显示/隐藏他们的子列表。我之前做过一些单击时会影响组件的每个实例的操作,因此当您单击 expand 按钮时,它将切换每个主要项目的子列表。

React 对我来说是新的,我将这个项目部分用作学习工具。我认为这与将状态绑定到组件的特定实例有关,但我不确定如何或在何处执行此操作。

这是组件:

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 中具有切换功能: &lt;button onClick={toggle}&gt;expand&lt;/button&gt; 和我有一个条件 if(isExpanded) 有两个渲染,一个带有 SummaryItemList 组件,一个没有。

除了映射对象之外,还有更好的方法吗?如何绑定切换的状态以仅影响它应该影响的实例?

【问题讨论】:

  • 正如您所解释的问题,该按钮仅在第一次时有效,对吗?

标签: reactjs binding state


【解决方案1】:

我认为您可能忘记为每个项目分配一个 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>

【讨论】:

  • 谢谢!我能够将其复制并使其正常工作,而几乎不做任何更改。我意识到我没有使用的一些不同之处首先是 1. List 组件的 key 属性和 2. 括起来的 React.Fragment 组件。我得再研究一下。但无论哪种方式,这对我来说都是一个很好的模板,可以用来学习和学习。谢谢!
猜你喜欢
  • 2022-11-09
  • 2019-11-11
  • 1970-01-01
  • 2012-12-13
  • 1970-01-01
  • 2018-09-23
  • 2018-04-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多