维护相同的状态变量以实现“显示更多/更少”功能

时间:2019-05-08 12:46:02

标签: reactjs typescript setstate

我有一个包含多张卡片的页面,其中每张卡片都有一个项目列表。我一直在尝试在每张卡片上实施Show More / Show Less实施。对于单张卡,我可以通过向状态对象添加两个属性来使其正确。但是,如果我对所有卡实施相同的操作,最终将为每个卡添加更多的状态对象属性。 寻找一种更好的方法,在这里我可以使用一种通用方法来处理所有卡,显示更多/更少实施

仅需要一种有效的方法来实现这一目标。 帮助将不胜感激

组件代码

仅包含两张卡的示例

import * as React from 'react';
interface IState{
  arr1:[],
  arr2: [],
  arr1ExpandFlag: boolean, // For updating Button label(More/Less)
  arr2ExpandFlag : boolean
  arr1temsToShow: number,  // Number of items to show
  arr2itemsToShow: number 
  //I will end up adding two variables one for each card
}
export default class App extends React.Component<{},IState> {

  constructor(props:any){
    super(props);
    this.state = {
      arr1 :[],
      arr2 :[],
      arr1ExpandFlag: false,
      arr1ExpandFlag: false,
      arr1itemsToShow: 3,
      arr2itemsToShow: 3,
    }
  }

  showMore = (type: string) => { // end up adding if conditions
    if(type === 'arr1')
    {
      (this.state.arr1itemsToShow === 3) ? 
      (this.setState({ arr1itemsToShow: this.state.arr1.length, arr1ExpandFlag: true })):
      (this.setState({ arr1itemsToShow: 3,arr1ExpandFlag: false}))
    }
    if(type === 'arr2')
    {
      (this.state.arr2itemsToShow === 3) ? 
      (this.setState({ arr2itemsToShow: this.state.arr2.length, arr2ExpandFlag: true })):
      (this.setState({ arr2itemsToShow: 3, arr2ExpandFlag: false}))
    }
  }

 render()    // This is just for two cards
 {
   return
   (
      <div> 
        <div>
          {this.state.arr1.slice(0, this.state.arr1itemsToShow).map((data : any, i) => 
            <p key={i}>{data.user}</p>
          )}
          <a onClick={() => this.showMore('arr1')}>
            { (this.state.arr1ExpandFlag) ? 
              ( <span>Show less</span>)   : 
              ( <span>Show more</span>)
            }
          </a>  
        </div>
       <div>
         {this.state.arr2.slice(0, this.state.arr2itemsToShow).map((data : any, i) => 
             <p key={i}>{data.user}</p>
         )}
         <a onClick={() => this.showMore('arr2')}>
          { (this.state.arr2ExpandFlag) ? 
            (<span>Show less</span>)   : 
            (<span>Show more</span>)
          }
         </a>  
      </div>
    </div>
   )
 }

1 个答案:

答案 0 :(得分:1)

正如其他人所说-将其构建为可重用的组件。首先确定要重复的地方,然后将其提取出来。练习变得更加容易。

我将从Card开始。您可以使用卡片类型(也可以使用界面,但这是个人喜好),然后添加onClickExpand处理程序以形成该控件的道具。

type Item = {
  user: string;
}

type Card = {
  items: Item[];
  expanded?: boolean;
  numItemsShowing: number;
}

type CardProps = Card & {
  onClickExpand: () => void;
};

const Card = (props: CardProps) => {
  const { expanded, items, numItemsShowing, onClickExpand } = props;
  return (
    <div>
      {items.slice(0, numItemsShowing).map((data, i) => (
        <p key={i}>{data.user}</p>
      ))}
      <a onClick={onClickExpand}>
        {expanded
          ? <span>Show less</span>
          : <span>Show more</span>
        }
      </a>
    </div>
  );
}

那么您的应用可以更简单:

type State = {
  card: Card[];
}

export default class App extends React.Component<{}, State> {
  state = { cards: [] };

  showMore = (index: number) => () => {
    this.setState({
      cards: this.state.cards.map((card, i) => {
        // Only modify card if it's the index we care about
        if (i === index) {
          return {
            ...card,
            expanded: true,
          }
        }
        return card;
      })
    });
  }

  addCard = () => {
    const newCard = {
      items: [],
      expanded: false,
      numItemsShowing: 0
    };

    this.setState({
      cards: [ ...this.state.cards, newCard ] // add to end of array
    });
  }

  render() {
    return (
      <div>
        {this.state.cards.map((card, i) =>
          <Card
            {...card}
            onClickExpand={this.showMore(i)}
            key={i}
          />
        )}

        <button onClick={this.addCard}>Add Card</button>
      </div>
    )
  }
}

此应用可让您单击按钮以将新卡添加到该状态。