What's the best way to store data locally?
Answered
David L. Bowman posted this in #help-forum
I'm building a "Reminder App" where a user can add, edit, and remove reminders. In brief, you set up your reminders and intervals, and it rings when you should be reminded.
I'm going to do auth for user data, and postgres for the reminders, intervals, etc., but i want the chat history to be saved locally. No need for this to be saved on the database.
What's the best way to save this type on data using Next.js 14?
I'm going to do auth for user data, and postgres for the reminders, intervals, etc., but i want the chat history to be saved locally. No need for this to be saved on the database.
What's the best way to save this type on data using Next.js 14?
24 Replies
local storage.
Answer
Only real option
Using the
window.localStorage API?If you dont wanna store the data yourself.
Yep
kk, I was playing around and creating a hook for this.
import { useState } from "react"
function useLocalStorage<T>(key: string, initialValue: T) {
const [storedValue, setStoredValue] = useState<T>(() => {
if (typeof window === "undefined") {
return initialValue
}
try {
const item = window.localStorage.getItem(key)
return item ? JSON.parse(item) : initialValue
} catch (error) {
console.log(error)
return initialValue
}
})
const setValue = (value: T | ((val: T) => T)) => {
try {
const valueToStore =
value instanceof Function ? value(storedValue) : value
setStoredValue(valueToStore)
if (typeof window !== "undefined") {
window.localStorage.setItem(key, JSON.stringify(valueToStore))
}
} catch (error) {
console.log(error)
}
}
return [storedValue, setValue] as const
}
export default useLocalStorageI was wondering if there was better practice.
not sure if that works yet, haven't really tested well.
remember, a single site can only take up 5mb of local storage, so you have to have some logic in there to handle it
@Jboncz remember, a single site can only take up 5mb of local storage, so you have to have some logic in there to handle it
I don't know what this means, i'm sorry.
I understand the limits.
but, I don't understand your recommended solution.
this is all just going to be text.
nvm the other comment.
kk, i'll get there when i get there 😄
if i hit a limit, i'll just clear the first half of the history
Yeah, you can do things to 'compress' the data, if you wanted. To make the 5mb go further if that makes sense?
ty for your answer 🙂
Np 🙂
in case if someone comes back or if you wanna see @Jboncz , this worked perfectly.
"use client"
import {
type CommandHistory,
TerminalHistory
} from "@/components/TerminalHistory"
import TerminalInput from "@/components/TerminalInput"
import TerminalPrompt from "@/components/TerminalPrompt"
import commands from "@/utilities/commands"
import { type ChangeEvent, type FormEvent, useEffect, useState } from "react"
export default function Terminal() {
const [command, setCommand] = useState("")
const [commandHistory, setCommandHistory] = useState<CommandHistory[]>([])
useEffect(() => {
const storedCommandHistory = localStorage.getItem("commandHistory")
if (storedCommandHistory) {
setCommandHistory(JSON.parse(storedCommandHistory))
}
}, [])
const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
setCommand(e.target.value)
}
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
const trimmedCommand = command.trim().toLowerCase()
const response = commands[trimmedCommand] || "Unknown command"
const currentTimestamp = new Date()
const id = currentTimestamp.getTime().toString()
const updatedCommandHistory = [
...commandHistory,
{ id, timestamp: currentTimestamp, command: trimmedCommand, response }
]
setCommandHistory(updatedCommandHistory)
localStorage.setItem(
"commandHistory",
JSON.stringify(updatedCommandHistory)
)
setCommand("")
}
return (
<main className="h-full border-2 rounded-md p-4 overflow-auto text-xs sm:text-sm md:text-base border-[#98971a] bg-[#282828] text-[#ebdbb2]">
<TerminalPrompt username="david" />
<div className="flex flex-col">
<TerminalHistory commandHistory={commandHistory} />
<TerminalInput
command={command}
onInputChange={handleInputChange}
onSubmit={handleSubmit}
/>
</div>
</main>
)
}Perfect! Good idea 🙂