You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React条件渲染子组件的面板高度动画实现咨询及react-spring可行性探讨

Fixing React Panel Height Animation (CSS & react-spring Solutions)

Hey there! Let's get that panel animation working for you. The core issue with your current code is that you're conditionally mounting/unmounting the content section—CSS transitions can't animate elements that are being added or removed from the DOM. Plus, we need explicit start/end values for properties like height to make transitions smooth. Let's cover two solid solutions:

Solution 1: CSS Transitions with React State

This approach keeps the content DOM element intact and uses React state to toggle its height, letting CSS handle the animation.

Step-by-Step Fix:

  • Remove the conditional rendering of the content div—keep it in the DOM at all times.
  • Use the isOpen state to control the height and overflow styles of the content.
  • Add a CSS transition to the panel's content container for the height property.

Here's the updated code:

const { useState } = React;
const Example = ({ title }) => {
  const [isOpen, setIsOpen] = useState(false);
  
  return (
    <>
      <div style={{ position: "relative", width: "100%", height: "100%", backgroundColor: "tomato" }}></div>
      <div className="panel" style={{ position: "absolute", bottom: 20, right: 20, backgroundColor: "pink", width: 200, padding: 15 }}>
        <div>Title</div>
        <div onClick={() => setIsOpen(!isOpen)} style={{ cursor: "pointer" }}>
          {isOpen ? "Close" : "Open"}
        </div>
        {/* Keep content div in DOM, animate height */}
        <div 
          className="panel-content"
          style={{ 
            overflowY: isOpen ? "scroll" : "hidden",
            height: isOpen ? "250px" : "0",
            transition: "height 0.3s ease"
          }}
        >
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
        </div>
      </div>
    </>
  );
};

// Fix the typo: ddocument → document
ReactDOM.render(
  <Example title="Example using Hooks:" />,
  document.getElementById("react")
);
html, body {
  width: 100%;
  height: 100%;
}
#react {
  width: 100%;
  height: 100%;
}
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Key Notes:

  • We replaced the separate "Open"/"Close" elements with a single toggle button to clean up the code.
  • The panel-content div always exists—we just toggle its height between 0 and 250px, with a CSS transition to smooth the change.
  • Fixed the typo ddocument in your original code (that would have broken rendering entirely!).

Solution 2: Using react-spring

If you want more control over animations (like custom easing, spring physics), react-spring is a great choice. Here's how to implement it correctly:

Step-by-Step Fix:

  1. Add the react-spring CDN to your HTML.
  2. Use the useSpring hook to create animated styles based on the isOpen state.
  3. Wrap your content in an animated.div to apply the spring animation.

Updated code:

const { useState } = React;
const { useSpring, animated } = reactSpring; // Import from react-spring

const Example = ({ title }) => {
  const [isOpen, setIsOpen] = useState(false);
  
  // Define spring animation for height
  const contentStyle = useSpring({
    height: isOpen ? "250px" : "0",
    overflow: isOpen ? "scroll" : "hidden",
    config: { tension: 200, friction: 20 } // Adjust spring physics here
  });
  
  return (
    <>
      <div style={{ position: "relative", width: "100%", height: "100%", backgroundColor: "tomato" }}></div>
      <div className="panel" style={{ position: "absolute", bottom: 20, right: 20, backgroundColor: "pink", width: 200, padding: 15 }}>
        <div>Title</div>
        <div onClick={() => setIsOpen(!isOpen)} style={{ cursor: "pointer" }}>
          {isOpen ? "Close" : "Open"}
        </div>
        {/* Use animated.div for spring animation */}
        <animated.div style={contentStyle}>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
        </animated.div>
      </div>
    </>
  );
};

ReactDOM.render(
  <Example title="Example using Hooks:" />,
  document.getElementById("react")
);
html, body {
  width: 100%;
  height: 100%;
}
#react {
  width: 100%;
  height: 100%;
}
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<!-- Add react-spring CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-spring/8.0.27/react-spring.min.js"></script>

Key Notes:

  • We import useSpring and animated from react-spring to create the animation.
  • The contentStyle object holds the animated properties—react-spring handles interpolating between the open/closed values automatically.
  • You can tweak the config object to adjust the spring's tension/friction for different animation feels.

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

火山引擎 最新活动