基于状态变化的条件渲染时,React 转换不起作用

问题描述 投票:0回答:1

我有一个切换按钮来更改布尔状态。当状态切换时,我希望一个特定的块随着转换而出现/消失。但过渡不起作用。我有什么遗漏的吗?

//Imports
const DriversDetails= () => {
    const [driversDiscount,setDriversDiscount]=useState(false)
  return (
   
                 <label htmlFor="" className="flex items-center gap-2 text-[#6F6464] font-semibold pb-2">
                     <ToggleButton value={driversDiscount} action={setDriversDiscount}/>
                        Do you want to offer discounts?
                      <ExclIcon/>
                 </label>   
                {driversDiscount && 
                    <div className="flex justify-between pb-4 transition-opacity duration-500 ease-in-out opacity-100">
                        <div>
                            <p className="font-semibold text-black-primary pb-1">Total amount <span className="text-[12px] text-black-light">(After discount)</span></p>
                            <p className="text-[14px] font-semibold text-black-light flex gap-2 items-center "><ToggleButton value={removeCents} action={setRemoveCents} />Remove cents</p>
                        </div>
                        <p className="text-right">
                            <span className='font-[700] text-[18px] ml-1'> $8</span>
                            <span className='text-[#151515] text-sm font-medium'>.29</span>
                        </p>
                    </div>}
   
  );
}
export default DriversDetails;
reactjs animation tailwind-css state css-transitions
1个回答
0
投票

对于 CSS 过渡到“播放”,元素必须在 DOM 中在过渡发生变化之前

driversDiscount
false
时,该元素不存在于 DOM 中。当
driversDiscount
更改为
true
时,该元素已经存在于 DOM 中,并由其
opacity: 1
类应用了
opacity-100
,因此
opacity
值没有变化,因此没有从
transition: opacity
的转换。

driversDiscount
true
然后改为
false
时,该元素会立即被移除,因此任何CSS过渡都没有机会播放。此外,即使它 did 有机会玩,也不会有
opacity
值变化,因此不会从
transition: opacity
进行转换。

这是使 CSS 转换正常工作的最低解决方案。我们:

  • 始终将元素保留在 DOM 中。
  • opacity
    为 false 时,将
    0
    值更改为
    driversDiscount
    ,这样过渡到补间时就有
    opacity
    值变化。

const { useState } = React;

const ToggleButton = ({ value, action }) => (
  <button type="button" onClick={() => action(!value)}>
    {String(value)}
  </button>
);

const ExclIcon = () => 'ExclIcon';

const DriversDetails = () => {
  const [driversDiscount, setDriversDiscount] = useState(false);
  const [removeCents, setRemoveCents] = useState(false);
  
  return (
    <React.Fragment>
      <label
        htmlFor=""
        className="flex items-center gap-2 text-[#6F6464] font-semibold pb-2"
      >
        <ToggleButton value={driversDiscount} action={setDriversDiscount} />
        Do you want to offer discounts?
        <ExclIcon />
      </label>
      <div className={`flex justify-between pb-4 transition-opacity duration-500 ease-in-out ${driversDiscount ? '' : 'opacity-0'}`}>
        <div>
          <p className="font-semibold text-black-primary pb-1">
            Total amount{" "}
            <span className="text-[12px] text-black-light">
              (After discount)
            </span>
          </p>
          <p className="text-[14px] font-semibold text-black-light flex gap-2 items-center ">
            <ToggleButton value={removeCents} action={setRemoveCents} />
            Remove cents
          </p>
        </div>
        <p className="text-right">
          <span className="font-[700] text-[18px] ml-1"> $8</span>
          <span className="text-[#151515] text-sm font-medium">.29</span>
        </p>
      </div>
    </React.Fragment>
  );
};

ReactDOM.createRoot(document.getElementById("app")).render(<DriversDetails />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.tailwindcss.com/3.4.3"></script>

<div id="app"></div>

© www.soinside.com 2019 - 2024. All rights reserved.