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

React.js灯光亮度滑块卡顿问题及平滑移动需求

解决React滑块拖动卡顿问题

问题根源

当前代码中,滑块的onChange事件直接触发lightOn函数,该函数会同步发起POST请求+GET请求,拖动滑块时每移动一次就触发一轮网络请求,大量异步请求阻塞主线程,导致UI冻结卡顿。

修复方案

  1. 分离本地状态更新与网络请求:拖动滑块时仅更新本地状态,松开滑块后再向服务器发送请求
  2. 移除子组件冗余状态:子组件无需维护全量设备列表light,复用父组件传递的属性或本地状态即可
  3. 避免全量设备查询:更新亮度后无需重新拉取所有设备,直接通过父组件同步状态即可

修改后的代码

DiscoverOffice.js

const DiscoverOffice = () => {
    const [light, setLight] = useState([]);
    
    const getDevices = async() => {
      try {
        const result = await axios.get('xxx.com', {
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${cookies.get('accesstoken')}`
          },
        });
        setLight(result.data.attributes.light);
      } catch (err) {
        console.log(err);
      }
    }

    useEffect(() => {
      getDevices();
    }, []);

    // 子组件调用该方法更新单设备亮度,无需拉取全量数据
    const updateLightBrightness = (entityId, newBrightness) => {
      setLight(prev => prev.map(item => 
        item.entity_id === entityId ? {...item, brightness: newBrightness} : item
      ));
    }

    return (
      <>
        {light.map((item) => 
          <LightSliderBar 
            key={item.entity_id}
            item={item} 
            updateBrightness={updateLightBrightness}
          />
        )}
      </>
    );
}
export default DiscoverOffice;

LightSliderBar.js

import { useState, useCallback } from 'react';

const LightSliderBar = ({ item, updateBrightness }) => {
    const cookies = new Cookies();
    const entity_id = item.entity_id;
    const [brightness_value, setBrightnessValue] = useState(item.brightness);
    
    // 向服务器同步亮度值
    const syncBrightnessToServer = useCallback(async () => {
      try {
        await axios.post('xxx.com', {
          entity_id: entity_id, 
          brightness: brightness_value
        }, {
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${cookies.get('accesstoken')}`
          },
        });
        // 通知父组件更新状态
        updateBrightness(entity_id, brightness_value);
        console.log('亮度更新成功');
      } catch (err) {
        console.log('亮度更新失败:', err);
        // 失败时回退到初始值
        setBrightnessValue(item.brightness);
      }
    }, [entity_id, brightness_value, cookies, updateBrightness, item.brightness]);
    
    // 拖动时仅更新本地状态
    const handleSliderChange = useCallback((e) => {
      setBrightnessValue(Number(e.target.value));
    }, []);

    return (
      <div>
          <input 
            className="range-input" 
            type="range" 
            name="speed" 
            min="0" 
            max="100" 
            id="slider"
            value={brightness_value} 
            onChange={handleSliderChange}
            onMouseUp={syncBrightnessToServer}
            onTouchEnd={syncBrightnessToServer} // 适配移动端触摸操作
            style={{ background: gradient, }}
          />
      </div>
    );
};

// 用React.memo避免父组件重渲染时子组件不必要刷新
export default React.memo(LightSliderBar);

额外优化建议

  • 若需要更严谨的请求控制,可对syncBrightnessToServer添加防抖处理,避免快速拖动松开后重复发送请求:
import { debounce } from 'lodash';
// 定义防抖后的请求函数
const debouncedSync = useCallback(debounce(syncBrightnessToServer, 300), [syncBrightnessToServer]);
// 替换onMouseUp/onTouchEnd的调用为debouncedSync

内容的提问来源于stack exchange,提问作者user20271619

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 07:35:19