反应倒计时没有重置或重新渲染第二次

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

我想做的是在更改状态后更新重置倒计时。

我正在从 API 中获取三种状态。

如果API返回带有时间戳的
future
,这个时间戳就是拍卖的开始时间,但是如果状态是
live
那么时间戳就是拍卖的结束时间。

所以在下面的代码中,我在 useEffect 中调用 api 来获取传递给倒计时的初始数据并且它有效,但是在

expired

 中的第一个完成我正在检查它的状态并更新 auctionStatus 而 
future
 正在检查更新到召回新时间戳的 API ..到目前为止它的工作和第二个时间戳出现但它已停止......意味着第二次不倒计时。

live

但是出现这个错误
handleRenderer

它的表现也很古怪,当第一次倒计时结束时,它向 handleRenderer 返回完整的真实值,所以我在那里检查它的 auctionStatus,但它来回移动。
    

您使用
auctionStatus
作为 useEffect 的依赖项。 当

response.status

相同时,
reactjs countdown
2个回答
1
投票
不会改变,所以您的

useEffect 不会被再次调用。 回答您关于如何解决问题的评论.. 我不确定你的逻辑,但我会通过这个简单的例子来解释。 useEffect 您可以简单地使用一个标志,而不是像这样从真到假不断变化:

import React, { useEffect, useState } from 'react'; import { atom, useAtom } from 'jotai'; import { useQuery } from 'react-query'; import { startTimeAtom, auctionStatusAtom, winningLosingTextAtom } from '../../atoms'; import { toLocalDateTime } from '../../utility'; import Countdown from 'react-countdown'; import Api from '../../services/api2'; async function getAuctionStatus() { return await Api.getAuctionStatus(); } const Counter = () => { // let countdownApi = null; let statusUpdateCount = true; // component states const [startTime, setStartTime] = useAtom(startTimeAtom); const [auctionStatus, setAuctionStatus] = useAtom(auctionStatusAtom); // this flag is used to trigger useEffect after any sort of change in auctionStatus const [flag, setFlag] = useState(true); useEffect(() => { getAuctionStatus().then((response) => { setAuctionStatus(response.status); setStartTime(toLocalDateTime(response.end_time, WpaReactUi.time_zone)); // countdownApi && countdownApi.start(); // later remove this }); }, [auctionStatus, flag, statusUpdateCount]); /** * It takes a formatted string and returns a JSX element to display the remaining time in the timer. * * @param {string} formatted - a string that contains the remaining time in the timer, formatted as an object * * @returns {JSX.Element} - a JSX element containing the remaining time in the timer, * displayed in divs with key-value pairs */ const displayCountDown = (formatted) => { return Object.keys(formatted).map((key) => { return ( <div key={`${key}`} className={`countDown bordered ${key}-box`}> <span className={`num item ${key}`}>{formatted[key]}</span> <span>{key}</span> </div> ); }); }; const CompletionResponse = () => { return <span className='auction-ended-text'>Auction ended</span>; }; /** * handleRenderer is a function that takes an object with two properties, completed and formatted, * and returns a JSX component depending on the value of the completed property. * * @param {Object} props - an object with two properties: * - completed {boolean} - indicates if the timer has completed * - formatted {string} - the current time left in the timer, formatted as a string * * @returns {JSX.Element} - a JSX component, either the <CompletionResponse /> component if the timer has completed, * or the displayCountDown(formatted) component if the timer is still running */ const handleRenderer = ({ completed, formatted }) => { if (completed) { if (statusUpdateCount) { setTimeout(() => { if (auctionStatus === 'future') { getAuctionStatus().then((response) => { console.log('setting auction status', response); setAuctionStatus(response.status); setFlag(!flag); statusUpdateCount = false; }); } }, 1000); } if (auctionStatus === null || auctionStatus === 'future') { return <span className='please-wait-text'>Auction is about to go live, Happy bidding!</span>; } else { // TODO later fix this, need to add API change setAuctionStatus('expired'); return <CompletionResponse />; } } return displayCountDown(formatted); }; return ( startTime && ( <div className="bidAuctionCounterContainer"> <div className="countdown-container"> <Countdown key={startTime} autoStart={true} id="bidAuctioncounter" date={startTime} intervalDelay={0} precision={3} renderer={handleRenderer} /> </div> </div> ) ); }; export default Counter;

看看下面的 useCountdown 挂钩:

https://codepen.io/AdamMorsi/pen/eYMpxOQ

0
投票
strument.js:108 Warning: Cannot update a component (`BiddingBlock`) while rendering a different component (`Countdown$1`). To locate the bad setState() call inside `Countdown$1`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render at Countdown$1 (webpack-internal:///./node_modules/react-countdown/dist/index.es.js:311:5) at div at div at Counter (webpack-internal:///./src/frontend/components/Counter/Counter.js:78:65) at div at section at main at div at div at div at BiddingBlock (webpack-internal:///./src/frontend/components/BiddingBlock/BiddingBlock.js:85:65) at div at SocketProvider (webpack-internal:///./src/frontend/services/socketProvider.js:60:23) at QueryClientProvider (webpack-internal:///./node_modules/react-query/es/react/QueryClientProvider.js:39:21) at Provider (webpack-internal:///./node_modules/jotai/esm/index.mjs:692:3) at App (webpack-internal:///./src/frontend/App.js:41:24) e

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