如何基于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
相关产品推荐
相关产品推荐

