You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于props与前props对比实现条件渲染及行颜色高亮?

嘿,这个需求我之前做实时数据表格高亮的时候刚好实现过,来给你捋捋最优方案和你的疑问~

最优实现方案

核心思路是追踪数值的前后变化,根据变化方向添加对应的光晕动画类,动画结束后自动移除类。这里分函数组件和类组件两种常见场景来写:

函数组件(React Hooks)

用useRef存储上一次的数值(不会触发重渲染),用useEffect监听当前数值的变化,对比后设置高亮状态:

import { useState, useEffect, useRef } from 'react';

const ValueRow = ({ currentValue }) => {
  const [highlightClass, setHighlightClass] = useState('');
  // 用ref存上一次的数值,不会引发重渲染
  const prevValueRef = useRef(null);

  useEffect(() => {
    // 第一次渲染时prevValueRef.current为null,跳过对比
    if (prevValueRef.current !== null) {
      let glowClass = '';
      if (currentValue > prevValueRef.current) {
        glowClass = 'green-glow';
      } else if (currentValue < prevValueRef.current) {
        glowClass = 'red-glow';
      }
      
      setHighlightClass(glowClass);
      // 1.5秒后移除高亮类,避免一直显示光晕
      const timer = setTimeout(() => setHighlightClass(''), 1500);
      return () => clearTimeout(timer);
    }
    // 更新ref为当前值,供下次对比用
    prevValueRef.current = currentValue;
  }, [currentValue]); // 只有currentValue变化时才执行

  return (
    <div className={`data-row ${highlightClass}`}>
      当前数值:{currentValue}
    </div>
  );
};

对应的CSS光晕动画:

.data-row {
  padding: 8px;
  margin: 4px 0;
  border-radius: 4px;
  transition: box-shadow 0.3s ease;
}

.green-glow {
  box-shadow: 0 0 10px rgba(76, 175, 80, 0.7);
  animation: fadeGlow 1.5s ease-out forwards;
}

.red-glow {
  box-shadow: 0 0 10px rgba(244, 67, 54, 0.7);
  animation: fadeGlow 1.5s ease-out forwards;
}

@keyframes fadeGlow {
  to {
    box-shadow: none;
    opacity: 0.9;
  }
}

类组件

用componentDidUpdate生命周期钩子对比前后props,然后设置高亮状态:

import React from 'react';

class ValueRow extends React.Component {
  state = {
    highlightClass: ''
  };

  componentDidUpdate(prevProps) {
    // 只有数值变化时才处理
    if (prevProps.currentValue !== this.props.currentValue) {
      let glowClass = '';
      if (this.props.currentValue > prevProps.currentValue) {
        glowClass = 'green-glow';
      } else if (this.props.currentValue < prevProps.currentValue) {
        glowClass = 'red-glow';
      }

      this.setState({ highlightClass: glowClass });
      // 自动移除高亮类
      setTimeout(() => this.setState({ highlightClass: '' }), 1500);
    }
  }

  render() {
    return (
      <div className={`data-row ${this.state.highlightClass}`}>
        当前数值:{this.props.currentValue}
      </div>
    );
  }
}
关于你提到的两个阶段的可行性分析

1. mapStateToProps 里做对比?→ 不推荐,也不可行

mapStateToProps是纯函数,它的职责只是把Redux state映射成组件props,不能存储状态或产生副作用。每次Redux state变化时它都会重新执行,没有办法保留上一次的props值,所以根本没法在这里做前后数值的对比。强行做的话会破坏纯函数的特性,导致逻辑混乱。

2. 渲染阶段做对比?→ 绝对不要这么做

渲染函数(不管是类组件的render还是函数组件的返回部分)必须是纯函数,只能依赖当前的props和state返回JSX。如果在渲染阶段对比前后值并调用setState,会直接触发无限重渲染循环(setState→渲染→setState→...),这是React的反模式,会严重影响性能甚至导致页面崩溃。

总结

最优方案就是用Hooks的useRef+useEffect(函数组件)或者类组件的componentDidUpdate来追踪数值变化,这种方式既符合React的设计原则,又能完美实现你要的光晕效果。

内容的提问来源于stack exchange,提问作者Tiago Bértolo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:33:18