簡體   English   中英

在 React 中關閉條件渲染組件時平滑 animation

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM