I'm migrating a Gatsby project from JS to TS, everything works fine in development, no errors on build, but when I use gatsby serve
or deploy somewhere else, I'm getting this error on browser console when I click in any button:
index.tsx
:
interface CVData {
name: string;
position: string;
address: string;
email: string;
website: string;
twitter: string;
github: string;
skills: string[];
languages: string[];
education: any[];
work: any[];
projects: any[];
awards: any[];
publications: any[];
interests: any[];
excerpt: string;
}
const [cvdata, setCVdata] = React.useState<CVData>({
name: "",
position: "",
address: "",
email: "",
website: "",
twitter: "",
github: "",
skills: [],
languages: [],
education: [],
work: [],
projects: [],
awards: [],
publications: [],
interests: [],
excerpt: "",
})
React.useEffect(() => {
setCVdata(JSON.parse(localStorage.getItem("cvdata") || '{}'))
}, [])
React.useEffect(() => {
localStorage.setItem("cvdata", JSON.stringify(cvdata))
}, [cvdata])
const [currentLang, setCurrentLang] = React.useState("")
const addlanguage = () => {
const newLangs = [...cvdata.languages, currentLang] // line that throws error
setCVdata({ ...cvdata, languages: newLangs })
setCurrentLang("")
}
const remlanguage = () => {
const newLangs = cvdata.languages.slice(0, -1) // line that throws error
setCVdata({ ...cvdata, languages: newLangs })
setCurrentLang("")
}
// and the buttons:
<button
type="button"
onClick={addlanguage}
className="border-2 border-blue-700 text-blue-700 font-bold p-2 hover:text-gray-300 hover:bg-blue-700 rounded-lg px-2 mb-2"
>
<Trans>Add</Trans>
</button>
<button
type="button"
onClick={remlanguage}
className="border-2 border-blue-700 text-blue-700 font-bold p-2 hover:text-gray-300 hover:bg-blue-700 rounded-lg px-2 mb-2"
>
<Trans>Remove</Trans>
</button>
I'm learning TS, so I'm using lots of any
, however I don't understand why it says that cvdata.languages
is undefined (it also throws error for every button in the form)
You can find the full code in this branch, especifically index.tsx
In case there's no "cvdata"
key set in localstorage, I modified the first useEffect
to
React.useEffect(() => {
setCVdata(JSON.parse(localStorage.getItem("cvdata") || JSON.stringify(emptycvdata)))
}, [])
where emptycvdata
is the default cvdata
object (the one I used in useState
)
However, that was not enough, I had to check for every key of cvdata
object in the onClick functions (otherwise missing keys would return undefined
).
For example, in addlanguage
I replaced
const newLangs = [...cvdata.languages, currentLang]
with
const newLangs = cvdata.languages ? [...cvdata.languages, currentLang] : [currentLang]
and
const newLangs = cvdata.languages.slice(0, -1)
with
const newLangs = cvdata.languages ? cvdata.languages.slice(0, -1) : []
I did the same for the other functions and everything seems to be fine now.