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

使用map()渲染Reactstrap AccordionItem时无法展开的问题排查

使用map()渲染Reactstrap AccordionItem时无法展开的问题排查

我帮你梳理下你遇到的问题,主要是几个细节没处理对,导致AccordionItem无法正常响应展开/收起操作,咱们一步步来修复:

1. 先修复toggle函数的逻辑错误

你当前的toggle函数里,当点击已展开的面板时,setOpen()没有传值,这会把open状态设为undefined,Reactstrap的Accordion无法正确识别这个状态。咱们把逻辑简化并修正:

const toggle = (id) => {
  // 点击已展开的面板就关闭(设为null),否则打开目标面板
  setOpen(open === id ? null : id);
};

2. 扔掉不可靠的全局i变量,改用post的唯一标识

你现在用的i变量是全局的(没有用let/const声明),每次组件重新渲染(比如状态变化时)都会被重置为1,导致targetId和accordionId在重新渲染时彻底混乱。直接用post自带的唯一id(比如post.id或post.post_key)作为Accordion的控制id,这才是最可靠的方案。

3. 修正Post组件的事件绑定与id匹配

Reactstrap的AccordionHeader需要手动绑定点击事件来触发toggle,同时要保证AccordionHeader的targetId和AccordionBody的accordionId完全对应,并且和父组件的open状态挂钩。

修改后的完整代码

Posts组件(父组件)

export function Posts({ posts, loading }) {
  // 初始设为null,默认所有面板都关闭
  const [open, setOpen] = useState(null);

  const toggle = (id) => {
    setOpen(open === id ? null : id);
  };

  // TRACE 日志保留你原来的逻辑
  if (process.env.REACT_APP_TRACE === "true") {
    console.log('TRACE: Posts: Posts({posts, loading})');
  };

  if (loading) {
    return <Loading />;
  };

  console.log("!!! open: " + open);

  return (
    <ul>
      <Accordion open={open}>
        {posts.map((post) => (
          <Post 
            key={post.post_key} 
            post={post}
            toggle={toggle} // 把toggle方法传给子组件
          />
        ))}
      </Accordion>
    </ul>
  )
};

Post组件(子组件)

export function Post({ post, toggle }) {
  // TRACE 日志保留你原来的逻辑
  if (process.env.REACT_APP_TRACE === "true") {
    console.log('TRACE: apiTestWpCom: Post(props)');
  };

  // 直接用post的唯一id作为Accordion的控制标识
  const targetId = post.id.toString();

  return (
    <AccordionItem>
      <AccordionHeader 
        targetId={targetId}
        // 点击时触发父组件的toggle,传入当前面板的id
        onClick={() => toggle(post.id)}
      >
        <p>
          <a href={post.url}>{post.title}</a><br />
          Site ID: {post.site_id}
        </p>
      </AccordionHeader>
      <AccordionBody accordionId={targetId}>
        <p>{post.excerpt}</p>
        <p>面板ID: {targetId}</p>
      </AccordionBody>
    </AccordionItem>
  )
};

核心问题总结

  1. toggle函数逻辑错误:之前的setOpen()无参调用导致状态异常,无法触发关闭动作
  2. 不可靠的id生成方式:全局i变量在组件重渲染时会被重置,导致面板标识混乱
  3. 事件绑定缺失:AccordionHeader没有绑定点击事件来触发toggle,状态变化无法传递到UI

按照上面的修改,应该就能正常展开/收起AccordionItem了,核心是用post自身的唯一ID替代手动维护的计数器,同时保证状态和UI的正确绑定。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 14:23:10