Last active
March 16, 2024 15:12
-
-
Save JacobThaDev/05cb313e9d9d4a5f13c58443159647ed to your computer and use it in GitHub Desktop.
NextJS maintain state across scopes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const [ account, setAccount ] = useState<AccountData>(); | |
const [ startUpdater, setStartUpdater ] = useState<boolean>(false); | |
const [ activeTimer, setActiveTimer ] = useState<any>(null); | |
// export this in your context to make a refresh button also. just call it. | |
// hence the 5 second throttle. lol. could possibly do some refining here on an edge case | |
// of where the auto-refresh comes close to the manual refesh. | |
const update = () => { | |
// can not be within 5 seconds of each other. | |
if (account.getLastUpdate() - new Date().getTime() < 5000) { | |
return; | |
} | |
// update account then reset the state so it updates! | |
// guaranteeeeees we stay in the same scope during this interval! | |
account.update().then((returnedScope: any) => { | |
let currentTime = new Date().getTime(); | |
setAccount(returnedScope); // update account data! | |
}); | |
} | |
useEffect(() => { | |
if (startUpdater) { | |
return; // no need to start again if mounted. | |
} | |
// create a new account | |
const accountScope = new AccountData(); | |
update() | |
setAccount(accountScope); | |
}, []); | |
// starts when `startUpdater` is toggeled to true above for the first time. | |
// ensures timer only starts once | |
useEffect(() => { | |
if (activeTimer) { | |
clearInterval(activeTimer); | |
setActiveTimer(null); | |
} | |
let newTimer = setInterval(() => { | |
update(); | |
}, updateDelay); | |
setActiveTimer(newTimer); | |
return () => { | |
if (activeTimer) { // this is mostly to solve a dev mount issue. lol. | |
clearInterval(activeTimer); | |
setActiveTimer(null); | |
} | |
} | |
}, [startUpdater]); | |
/** | |
* using a class for this to ensure I can stay in the same scope. | |
* let scope = this; | |
* setTimeout(() => scope.doSomething()); | |
* const { accountData } = someContext(); | |
*/ | |
class AccountData { | |
private accountData; | |
private updateState; | |
/** | |
* update all variables and return self. | |
* @returns this scrope | |
*/ | |
public async update() { | |
this.updateState = "updating"; | |
try { | |
// get your api response here and set this.accountData | |
this.lastUpdate = new Date().getTime(); | |
this.updateState = "idle"; | |
} catch (err) { | |
console.log(err); | |
this.updateState = "error"; | |
} | |
console.log(response); | |
return this; | |
} | |
public getAccountData() { | |
return this.accountData; | |
} | |
public setAccountData(data:any) { | |
this.accountData = data; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment