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

子组件应用Transition无效果,父组件应用则正常的问题

问题分析与解决方案

问题核心是内部定义的组件每次父组件重渲染时会被重新创建,导致DOM元素卸载重建,过渡动画失效。

你的代码里,InnerComponent定义在OuterComponent内部,当sidebarCtx.isOpen变化触发父组件重渲染时,InnerComponent会被重新定义为一个全新的组件类型,React会卸载旧的子组件DOM,再挂载新的,这就跳过了CSS过渡动画的触发条件(需要同一DOM元素的样式变化)。而把样式放在外层div时,外层DOM不会被重建,样式变化自然能触发过渡。

解决方案1:将子组件移到父组件外部

把InnerComponent移到OuterComponent外面,避免每次父组件重渲染都创建新组件:

import { useContext } from 'react';
import { SidebarContext } from './your-context-path';

const InnerComponent = ({ className, children }) => {
  return (
    <div className={className}>
      {children}
      <a>testing</a>
    </div>
  );
};

export const OuterComponent = () => {
  const sidebarCtx = useContext(SidebarContext);

  const style = 
    "w-[100px] h-[60px] transition-all duration-1000 bg-purple-900 text-2xl text-white " +
    (sidebarCtx.isOpen ? "w-[400px]" : "");

  return (
    <InnerComponent className={style} />
  );
};

解决方案2:用useMemo缓存内部子组件

如果必须在父组件内部定义子组件,用useMemo缓存组件,确保只有依赖变化时才重新创建:

import { useContext, useMemo } from 'react';
import { SidebarContext } from './your-context-path';

export const OuterComponent = () => {
  const sidebarCtx = useContext(SidebarContext);

  const style = 
    "w-[100px] h-[60px] transition-all duration-1000 bg-purple-900 text-2xl text-white " +
    (sidebarCtx.isOpen ? "w-[400px]" : "");

  const InnerComponent = useMemo(() => {
    return ({ children }) => {
      return (
        <div className={style}>
          {children}
          <a>testing</a>
        </div>
      );
    };
  }, [style]); // 依赖style,只有style变化时才重新创建组件

  return (
    <InnerComponent />
  );
};

解决方案3:将样式作为props传入子组件

另一种方式是把style作为props传给子组件,而不是让子组件直接引用父组件的变量,同时确保子组件不被重复创建:

import { useContext } from 'react';
import { SidebarContext } from './your-context-path';

const InnerComponent = ({ style, children }) => {
  return (
    <div className={style}>
      {children}
      <a>testing</a>
    </div>
  );
};

export const OuterComponent = () => {
  const sidebarCtx = useContext(SidebarContext);

  const style = 
    "w-[100px] h-[60px] transition-all duration-1000 bg-purple-900 text-2xl text-white " +
    (sidebarCtx.isOpen ? "w-[400px]" : "");

  return (
    <InnerComponent style={style} />
  );
};

以上三种方案都能避免子组件被重复创建,保证DOM元素的连续性,从而让Tailwind的过渡动画正常触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:39:40