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

React实现侧边栏展开收起:更新尺寸遇只读属性错误如何解决?

React侧边导航栏展开/迷你切换:解决TypeError修改只读style对象的问题

我想要实现类似AdminLTE的侧边导航栏展开/迷你切换功能,但在React中更新导航栏尺寸时遇到了错误。以下是我的测试代码,用setTimeout模拟点击触发宽度变化,结果抛出TypeError: Cannot assign to read only property 'width' of object '#<Object>':

import React, { Component } from 'react';
class SideNavBar extends Component {
  render() {
    let sideBarStyle = {
      'height': '100%',
      'backgroundColor': 'lightblue',
      'width': "80px",
      'position': 'absolute',
      'top': '0',
      'left': '0'
    }
    setTimeout(() => {
      sideBarStyle["width"] = "300px";
    }, 1000)
    return (
      <div style={sideBarStyle}> sidenavbar </div>
    );
  }
}
export default SideNavBar;

请问如何通过点击事件正确更新元素尺寸?


核心原因

这个问题我之前也碰到过,核心原因是你直接修改了React内联样式对象的属性——React会把传递给元素的style对象标记为只读(不可变),直接赋值修改会触发只读属性错误。正确的做法是通过**组件状态(state)**来管理样式变化,当state更新时,React会自动重新渲染组件并应用新的样式。

方法一:用State管理内联样式

我们可以把侧边栏的宽度存在组件的state里,通过点击事件更新state,从而触发样式变化:

import React, { Component } from 'react';

class SideNavBar extends Component {
  // 初始化state,默认是迷你宽度
  state = {
    sidebarWidth: '80px'
  };

  // 切换宽度的方法
  toggleSidebar = () => {
    this.setState(prevState => ({
      sidebarWidth: prevState.sidebarWidth === '80px' ? '300px' : '80px'
    }));
  };

  render() {
    const sideBarStyle = {
      height: '100%',
      backgroundColor: 'lightblue',
      width: this.state.sidebarWidth,
      position: 'absolute',
      top: '0',
      left: '0',
      cursor: 'pointer', // 添加上手型,提示可点击
      transition: 'width 0.3s ease' // 添加上过渡动画,和AdminLTE效果一致
    };

    return (
      <div style={sideBarStyle} onClick={this.toggleSidebar}>
        sidenavbar
      </div>
    );
  }
}

export default SideNavBar;

方法二:用CSS类切换(更推荐)

实际项目中,更推荐用CSS类来控制样式变化,这样代码更清晰,也方便扩展更多样式(比如导航文字的显示/隐藏):

首先定义CSS文件(比如SideNavBar.css):

.sidebar {
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background-color: lightblue;
  cursor: pointer;
  transition: width 0.3s ease;
}

.sidebar--mini {
  width: 80px;
}

.sidebar--expanded {
  width: 300px;
}

然后修改组件:

import React, { Component } from 'react';
import './SideNavBar.css'; // 引入CSS文件

class SideNavBar extends Component {
  state = {
    isExpanded: false
  };

  toggleSidebar = () => {
    this.setState(prevState => ({
      isExpanded: !prevState.isExpanded
    }));
  };

  render() {
    const sidebarClass = this.state.isExpanded 
      ? 'sidebar sidebar--expanded' 
      : 'sidebar sidebar--mini';

    return (
      <div className={sidebarClass} onClick={this.toggleSidebar}>
        sidenavbar
      </div>
    );
  }
}

export default SideNavBar;

补充:原代码报错的深层原因

在你的原代码中,sideBarStyle是在render方法里创建的普通对象,但React在处理内联样式时,会把这个对象包装成只读的不可变对象。当你在setTimeout里尝试修改它的width属性时,就会触发只读属性的错误。而通过state管理的话,每次state更新都会重新创建新的样式对象,完美避开了直接修改只读对象的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:30:14