简体   繁体   中英

How to limit and control the number of click on button per day or per hour in ReactJs

How to limit and control the number of click on button per day (or per hour) in ReactJs

any help please

How to limit and control the number of click on button per day (or per hour) in ReactJs

You can't restrict this in React. I explained this in a comment :

This is something that you must validate in your private code (back end / server / etc.). You must assume that the user of your client (React) app has complete control over the view, state (JavaScript), network requests, etc., so any attempts to restrict actions on the client can be subverted/bypassed by the user.

So, you'll need to validate this in other private code that's not running in your client app.


With that out of the way, and acknowledging that the user can manipulate the state of your client app, let's explore an implementation of the kind of quota you asked about on the client (just for fun) with a custom hook: useQuota :

Note that the hook doesn't use timers directly because timers on the order of hours/days are imprecise/unreliable.

Code in TypeScript Playground

 <div id="root"></div><script src="https://unpkg.com/react@18.2.0/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@18.2.0/umd/react-dom.development.js"></script><script src="https://unpkg.com/@babel/standalone@7.18.8/babel.min.js"></script><script>Babel.registerPreset('tsx', {presets: [[Babel.availablePresets['typescript'], {allExtensions: true, isTSX: true}]]});</script> <script type="text/babel" data-type="module" data-presets="tsx,react"> // import ReactDOM from 'react-dom/client'; // import { // StrictMode, // useCallback, // useRef, // useState, // type ReactElement, // } from 'react'; // This Stack Overflow snippet demo uses UMD modules // instead of the commented import statments above const { StrictMode, useCallback, useRef, useState, } = React; type QuotaUsageResult = { /** * When your remaining value will increase next. * Will always be a Date unless your quota limit is `0`. */ nextIncrease: Date | null; /** Non-negative integer */ remaining: number; /** Whther or not the quota usage succeeded */ success: boolean; }; type QuotaCallback = (result: QuotaUsageResult) => void; type QuotaOptions = { /** Milliseconds. eg 10 seconds = `10_000` */ expirationInterval: DOMHighResTimeStamp; /** Non-negative integer */ limit: number; }; function useQuota ( {expirationInterval, limit}: QuotaOptions, callback: QuotaCallback, ): () => void { const [timeStamps, setTimeStamps] = useState<EpochTimeStamp[]>([]); return useCallback(() => { const now = Date.now(); const timeStampLimit = now - expirationInterval; const notExpired = [...timeStamps.filter(ts => ts > timeStampLimit), now]; const quotaExceeded = notExpired.length > limit; if (quotaExceeded) while (notExpired.length > limit) notExpired.pop(); setTimeStamps(notExpired); const [oldest] = notExpired; const nextIncrease = oldest ? new Date(now + oldest - timeStampLimit) : null; const result: QuotaUsageResult = { nextIncrease, remaining: limit - notExpired.length, success: !quotaExceeded, }; callback(result); }, [callback, limit, expirationInterval, timeStamps]); } function App (): ReactElement { const timerIdRef = useRef(0); const [buttonText, setButtonText] = useState('Next'); const [info, setInfo] = useState('Click the button to begin'); // Set the limit to 4 actions, every 10s const onClick = useQuota({expirationInterval: 10e3, limit: 4}, (result) => { const {nextIncrease, remaining, success} = result; // Cancel previous timer clearTimeout(timerIdRef.current); // Indicate whether actions remain setButtonText(remaining === 0 ? 'Wait' : 'Next'); let updatedInfo = `Success: ${success ? 'true' : 'false'}`; updatedInfo += `, Remaining: ${remaining}`; if (nextIncrease) { updatedInfo += `, Next increase at: ${nextIncrease.toLocaleTimeString()}`; // Set a timer to update the button text the next time the quota increases const msUntilNextIncrease = nextIncrease.getTime() - Date.now(); timerIdRef.current = setTimeout(() => setButtonText('Next'), msUntilNextIncrease); } setInfo(updatedInfo); }, ); return ( <div> <div>{info}</div> <button {...{onClick}}>{buttonText}</button> </div> ); } const reactRoot = ReactDOM.createRoot(document.getElementById('root')!); reactRoot.render( <StrictMode> <App /> </StrictMode> ); </script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM