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

React Accordion组件中onToggle函数报“not a function”错误求助

CbdsAccordion组件onToggle "not a function" 错误排查与修复

开发CbdsAccordion组件时遇到问题:调用onToggle函数时持续触发“not a function”错误,尝试在props、默认props及map循环中定义onToggle,要么报错要么提示未使用。原代码如下:

import { useState } from "react";
import PropTypes from "prop-types";
import './CbdsAccordion.scss';

const CbdsAccordion = ({
  items,
  multiple = false
}) => {

  const [active, setActive] = useState(0);
  const [visibility, setVisibility] = useState(false);

  const isActive = () => (multiple ? visibility : active);

  const toggleVisibility = ({onToggle}) => {
    setVisibility((visible) => !visible);
    onToggle();
  };

  return (
    <div className='cbds-c-accordion'>

      {items.map((item, index) => (
        <div className={`card ${isActive() ? "accordion-active" : ""}`}
          key={index}
          active={active === index}
          multiple={multiple}
          onToggle={() => setActive((active => active === index ? '' : index))}
        >
          <div className='card-header' onClick={toggleVisibility}>
            {item.accordionLabel}
            <span className='accordion-icon'>+</span>
          </div>
          <div className='card-body'>
            {item.accordionPanel}
          </div>
        </div>
      )
      )}
    </div>
  )
}


CbdsAccordion.propTypes = {
  multiple: PropTypes.bool,
  active: PropTypes.bool
};

CbdsAccordion.defaultProps = {
  multiple: false,
  active: false
};

export default CbdsAccordion

错误原因分析

  • toggleVisibility参数错误:该函数尝试解构onToggle参数,但点击事件触发时未传递任何参数,导致onToggle为undefined,调用时触发"not a function"错误。
  • 无效的props传递:将onToggle作为原生div的props无意义,div不会处理该属性,也无法传递到点击事件中。
  • 状态逻辑混乱:
    • 多选模式用单个布尔值visibility控制所有项的展开/收起,不符合多选需求;
    • isActive函数返回值类型不统一(多选返回布尔,单选返回数字),导致类名判断逻辑错误。
  • props定义缺失:组件未将onToggle作为可接收的props,父组件无法传入回调,自定义的onToggle也未正确关联。

修复方案及完整代码

import { useState } from "react";
import PropTypes from "prop-types";
import './CbdsAccordion.scss';

const CbdsAccordion = ({
  items,
  multiple = false,
  onToggle // 新增:接收父组件传入的回调
}) => {
  // 调整状态:多选用数组存活跃索引,单选存单个索引
  const [activeIndexes, setActiveIndexes] = useState(multiple ? [] : 0);

  // 修正isActive:判断当前索引是否处于活跃状态
  const isActive = (index) => {
    if (multiple) {
      return activeIndexes.includes(index);
    }
    return activeIndexes === index;
  };

  // 重构toggle函数:接收当前索引,处理不同模式的状态切换
  const toggleVisibility = (index) => {
    let newActive;
    if (multiple) {
      // 多选模式:切换当前索引的活跃状态
      newActive = activeIndexes.includes(index)
        ? activeIndexes.filter(i => i !== index)
        : [...activeIndexes, index];
    } else {
      // 单选模式:切换当前索引,或取消(如果已经是活跃状态)
      newActive = activeIndexes === index ? null : index;
    }
    setActiveIndexes(newActive);
    
    // 调用外部传入的onToggle(如果存在)
    if (typeof onToggle === 'function') {
      onToggle(index, newActive);
    }
  };

  return (
    <div className='cbds-c-accordion'>
      {items.map((item, index) => (
        <div 
          className={`card ${isActive(index) ? "accordion-active" : ""}`}
          key={index}
        >
          <div className='card-header' onClick={() => toggleVisibility(index)}>
            {item.accordionLabel}
            <span className='accordion-icon'>{isActive(index) ? "-" : "+"}</span>
          </div>
          {isActive(index) && ( // 仅当活跃时渲染内容
            <div className='card-body'>
              {item.accordionPanel}
            </div>
          )}
        </div>
      ))}
    </div>
  )
}

CbdsAccordion.propTypes = {
  multiple: PropTypes.bool,
  items: PropTypes.arrayOf(PropTypes.shape({
    accordionLabel: PropTypes.node.isRequired,
    accordionPanel: PropTypes.node.isRequired
  })).isRequired,
  onToggle: PropTypes.func // 新增:定义onToggle的prop类型
};

CbdsAccordion.defaultProps = {
  multiple: false
};

export default CbdsAccordion

关键修改点

  1. 状态优化:根据multiple模式选择合适的状态类型(数组/单个值),实现正确的多选/单选逻辑。
  2. 修正点击事件:点击时传递当前项的索引给toggleVisibility,不再依赖无效的props传递。
  3. onToggle处理:将onToggle作为组件props接收,仅在它是函数时才调用,避免报错。
  4. 渲染逻辑优化:仅当项处于活跃状态时渲染card-body,同时更新图标显示(+/-切换)。
  5. props类型完善:补充items的必填类型定义,明确onToggle的函数类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 16:53:26