我想做的是在更改状态后更新重置倒计时。
我正在从 API 中获取三种状态。
如果API返回带有时间戳的
future
,这个时间戳就是拍卖的开始时间,但是如果状态是
live
那么时间戳就是拍卖的结束时间。所以在下面的代码中,我在 useEffect 中调用 api 来获取传递给倒计时的初始数据并且它有效,但是在
expired
中的第一个完成我正在检查它的状态并更新 auctionStatus 而
future
正在检查更新到召回新时间戳的 API ..到目前为止它的工作和第二个时间戳出现但它已停止......意味着第二次不倒计时。
live
但是出现这个错误
handleRenderer
它的表现也很古怪,当第一次倒计时结束时,它向 handleRenderer 返回完整的真实值,所以我在那里检查它的 auctionStatus,但它来回移动。您使用
auctionStatus作为 useEffect 的依赖项。 当
response.status
相同时,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
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