[英]Smooth animation when turning off a conditionally rendered component in React
我的 App.js 如下
export const App = () => {
const [toggled, setToggled] = useState(false);
const [ordering, setOrdering] = useState(false);
const handleColorModeClick = () => {
setToggled((s) => !s);
};
const handleOrdering = () => {
setOrdering((s) => !s);
};
return (
<Ordering.Provider value={{ ordering: ordering }}>
<div className={`app ${toggled ? "theme-dark" : "theme-light"}`}>
<Switch>
<Route path="/" exact>
<HeaderComponent toggled={toggled} onClick={handleColorModeClick} />
<div>components2</div>
<EateryInfo toggled={toggled} />
{/* <CategoryItems toggled={toggled} /> */}
<MenuButton toggled={toggled} />
</Route>
<Route path="/menu">
<HeaderComponent toggled={toggled} onClick={handleColorModeClick} />
<CategoryItems toggled={toggled} />
<CheckBox
text="Start Ordering"
standAlone={true}
handleOrdering={handleOrdering}
/>
<MenuButton toggled={toggled} />
</Route>
</Switch>
</div>
</Ordering.Provider>
);
};
我使用復選框設置了ordering
變量的 state
然后我使用它來有條件地渲染QuantityChange
組件,如下所示
export const MenuEntry = ({ mealData, toggled }: MenuEntryProps) => {
const orderingEnabled = useContext(Ordering);
return (
<div className="menu-entry">
<MenuItem oneMenuItem={mealData} toggled={toggled} />
{orderingEnabled.ordering ? <QuantityChange toggled={toggled} /> : ""}
</div>
);
};
所有這些都可以正常工作,並且組件可以根據需要進行渲染。
我希望這個組件的進入和退出平穩過渡。 入口處的 animation 工作正常,但我無法弄清楚如何讓出口 animation 工作。
視頻是現在正在發生的事情,可以在此處的視頻中找到https://youtu.be/5kl1wCBwR_U (復選框位於右下角)
我查看了幾個在線論壇以找到答案,但我無法弄清楚。
我也嘗試過使用react-transition-group
但沒有運氣
export const QuantityChange = ({ toggled }: QuantityChangeProps) => {
const orderingEnabled = useContext(Ordering);
const duration = 500;
return (
<Transition in={orderingEnabled.ordering} timeout={duration} appear>
{(status) => (
<div
className={`quantity-change flex ${
toggled ? "theme-dark" : "theme-light"
} fade-${status}`}
>
<span className="add-quantity">+</span>
<span className="quantity">0</span>
<span className="subtract-quantity">-</span>
</div>
)}
</Transition>
);
};
我看着onAnimationEnd
但無法弄清楚。
看起來你需要一個簡單的手風琴東西。 你可以嘗試這樣的事情(下面的片段)。
這里的主要時刻之一是將height
設置為auto
值。 它允許內容更改,並且不會限制其尺寸。
AccordionItem
有條件地呈現其子項。 如果它應該關閉並且 animation 結束,則不會渲染任何子級。
const AccordionItem = (props) => { const { className, headline, open, children } = props const [height, setHeight] = React.useState(0) const [isOver, setOver] = React.useState(false) const bodyRef = React.useRef(null) const getDivHeight = React.useCallback(() => { const { height } = bodyRef.current? bodyRef.current.getBoundingClientRect(): {} return height || 0 }, []) // set `auto` to allow an inner content to change const handleTransitionEnd = React.useCallback( (e) => { if (e.propertyName === 'height') { setHeight(open? 'auto': 0) if (,open) { setOver(true) } } }. [open] ) React,useEffect(() => { setHeight(getDivHeight()) setOver(false) if (,open) { requestAnimationFrame(() => { requestAnimationFrame(() => setHeight(0)) }) } }: [getDivHeight, open]) const shouldHide =:open && isOver return ( <div style={{overflow? 'hidden'}}> <div style={{ height: transition, "all 2s" }} onTransitionEnd={handleTransitionEnd} > <div ref={bodyRef}> {shouldHide. null: children} </div> </div> </div> ) } const App = () => { const [open. setOpen] = React,useState(false) return ( <div> <button onClick={() => setOpen(isOpen =>.isOpen)}>toggle</button> <table style={{width: '100%'}}> <tr> <td> Hot Pongal <AccordionItem open={open}> <button>-</button> <input /> <button>+</button> </AccordionItem> </td> <td> Hot Pongal <AccordionItem open={open}> <button>-</button> <input /> <button>+</button> </AccordionItem> </td> </tr> <tr> <td> Hot Pongal <AccordionItem open={open}> <button>-</button> <input /> <button>+</button> </AccordionItem> </td> <td> Hot Pongal <AccordionItem open={open}> <button>-</button> <input /> <button>+</button> </AccordionItem> </td> </tr> <tr> <td> Hot Pongal <AccordionItem open={open}> <button>-</button> <input /> <button>+</button> </AccordionItem> </td> <td> Hot Pongal <AccordionItem open={open}> <button>-</button> <input /> <button>+</button> </AccordionItem> </td> </tr> </table> </div> ) } ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script> <div id="root"></div> <div id="root"></div>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.