React-实现切换tab高亮显示和排序

 1、切换className

<div className="tab-list">
  { tabList.map(item => (
    <span key={item.type} className={`tab-box ${item.type === type ? 'active' : ''}`} onClick={() => handleClickTab(item.type)}>{ item.name }</span>
  ))}
</div>

2、classNames优化类名控制

        上面1的写法如果类名非常多的情况下比较复杂,我们可以引入classNames优化类名控制

// 安装
npm i classnames
// 引入
import classNames from 'classnames';

// 使用
<div className="tab-list">
  { tabList.map(item => (
    <span key={item.type} className={classNames('tab-box', {active: item.type === type})} 
    onClick={() => handleClickTab(item.type)}>{ item.name }</span>
  ))}
</div>

3、切换时触发重新排序

        以下方法切换tab时不会切换排序,因为这里原地修改原数组,但React的setState需要通过新引用触发重新渲染。由于原数组的引用未改变,React无法感知变化

const [commentList, setCommentList] = useState(list.sort((x, y) => new Date(y.ctime) - new Date(x.ctime)))

const [type, setType] = useState('new')
const handleClickTab = (type) => {
  setType(type)
  if (type === 'new') {
    setCommentList(commentList.sort((x, y) => new Date(y.ctime) - new Date(x.ctime)))
  } else {
    setCommentList(commentList.sort((x, y) => y.like - x.like))
  }
}

        修改方法一:

setCommentList([...commentList].sort((x, y) => new Date(y.ctime) - new Date(x.ctime)))

        修改方法二:函数式更新 => 推荐

setCommentList(prev => prev.sort((x, y) => new Date(y.ctime) - new Date(x.ctime)))

3、完整代码

import { useState } from "react";

const list = [
  { 
    id: 1,
    user: {
      uid: '12244',
      avatar: 'https://img0.baidu.com/it/u=2191392668,814349101&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1399',
      uname: '周杰伦'
    },
    content: '哎哟,不错哦',
    ctime: '2021-06-08 19:35:47',
    like: 88
  },
  { 
    id: 2,
    user: {
      uid: '12245',
      avatar: 'https://img0.baidu.com/it/u=2191392668,814349101&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1399',
      uname: '林俊杰'
    },
    content: '好听呀',
    ctime: '2021-06-15 19:35:47',
    like: 52
  },
  { 
    id: 3,
    user: {
      uid: '12246',
      avatar: 'https://img0.baidu.com/it/u=2191392668,814349101&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1399',
      uname: '周笔畅'
    },
    content: '呵呵哈哈哈',
    ctime: '2021-06-02 19:35:47',
    like: 192
  }
]

const userInfo = {
  uid: '12245',
  avatar: 'https://img0.baidu.com/it/u=2191392668,814349101&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1399',
  uname: '林俊杰'
}

const tabList = [
  { type: 'new', name: '最新' },
  { type: 'hot', name: '最热' },
]

function App() {
  const [commentList, setCommentList] = useState(list.sort((x, y) => new Date(y.ctime) - new Date(x.ctime)))
  const handleDelete = (id) => {
    setCommentList(commentList.filter(item => item.id !== id))
  }

  const [type, setType] = useState('new')
  const handleClickTab = (type) => {
    setType(type)
    if (type === 'new') {
      // 不会切换排序,因为这里原地修改原数组,但React的setState需要通过新引用触发重新渲染。由于原数组的引用未改变,React无法感知变化
      // setCommentList(commentList.sort((x, y) => new Date(y.ctime) - new Date(x.ctime)))
      // 修改方法一
      // setCommentList([...commentList].sort((x, y) => new Date(y.ctime) - new Date(x.ctime)))
      // 修改方法二(函数式更新 => 推荐)
      setCommentList(prev => prev.sort((x, y) => new Date(y.ctime) - new Date(x.ctime)))
    } else {
      // setCommentList(commentList.sort((x, y) => y.like - x.like))
      // setCommentList([...commentList].sort((x, y) => y.like - x.like))
      setCommentList(prev => prev.sort((x, y) => y.like - x.like))
    }
  }

  return (
    <div className="App">
      <div className="tab-list">
        { tabList.map(item => (
          <span key={item.type} className={`tab-box ${item.type === type ? 'active' : ''}`} onClick={() => handleClickTab(item.type)}>{ item.name }</span>
        ))}
      </div>
      <div className="user-list">
        { commentList.map((item, index) => (
          <div key={index} className="user-box">
            <img style={{width: 40, height: 40}} src={item.user.avatar} />
            <span>{ item.user.uname }</span>
            <div>{ item.content }</div>
            <div>{ item.ctime }</div>
            <span>点赞数:{ item.like }</span>
            { userInfo.uid === item.user.uid && <button onClick={() => handleDelete(item.id)}>删除</button> }
          </div>
        ))}
      </div>
    </div>
  );
}

export default App;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值