I am following Colt Steele’s React course. Sadly, the course is outdated so I chose to use function components instead of class based ones.
Currently I am stuck on a problem that I don’t understand. I’ll show my code and the error message.
colorHelpers.js:7 Uncaught TypeError: Cannot read properties of undefined (reading 'paletteName')
at generatePalette (colorHelpers.js:7:1)
at PaletteWrapper (App.js:17:1)
at renderWithHooks (react-dom.development.js:16305:1)
at mountIndeterminateComponent (react-dom.development.js:20074:1)
at beginWork (react-dom.development.js:21587:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
at invokeGuardedCallback (react-dom.development.js:4277:1)
at beginWork$1 (react-dom.development.js:27451:1)
at performUnitOfWork (react-dom.development.js:26557:1)
App.js
import { Routes, Route, useParams } from "react-router-dom";
import { generatePalette } from "./colorHelpers";
import Palette from "./Palette";
import seedColors from "./seedColors";
function App() {
const findPalette = (id) => {
const palette = seedColors.find((palette) => palette.id === id);
console.log(palette);
return palette;
};
const PaletteWrapper = () => {
const { id } = useParams();
const palette = generatePalette(findPalette(id));
return <Palette palette={palette} />;
};
return (
<div className="App">
<Routes>
<Route path="/" element={<h1>Welcome Home</h1>} />
<Route path="/palette/:id" element={<PaletteWrapper />} />
</Routes>
{/* <Palette palette={generatePalette(seedColors[3])} /> */}
</div>
);
}
export default App;
Palette.js
import { useState } from "react";
import ColorBox from "./ColorBox";
import { Navbar } from "./Navbar";
import "./Palette.css";
const Palette = (props) => {
const [level, setLevel] = useState(500);
const [format, setFormat] = useState("hex");
const changeFormat = (format) => {
setFormat(format);
};
const changeLevel = (newLevel) => {
setLevel(newLevel);
};
const { colors, paletteName, emoji } = props.palette;
const colorBoxes = colors[level].map((color) => (
<ColorBox key={color.name} background={color[format]} name={color.name} />
));
return (
<div className="Palette">
<Navbar
level={level}
changeLevel={changeLevel}
changeFormat={changeFormat}
format={format}
/>
<div className="Palette-colors">{colorBoxes}</div>
<div className="Palette-footer">
{paletteName}
<span className="emoji">{emoji}</span>
</div>
</div>
);
};
export default Palette;
colorHelpers.js
import chroma from "chroma-js";
const levels = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900];
export function generatePalette(starterPalette) {
let newPalette = {
paletteName: starterPalette.paletteName,
id: starterPalette.id,
emoji: starterPalette.emoji,
colors: {},
};
for (let level of levels) {
newPalette.colors[level] = [];
}
for (let color of starterPalette.colors) {
let scale = getScale(color.color, 10).reverse();
for (let i in scale) {
newPalette.colors[levels[i]].push({
name: `${color.name} ${levels[i]}`,
id: color.name.toLowerCase().replace(/ /g, "-"),
hex: scale[i],
rgb: chroma(scale[i]).css(),
rgba: chroma(scale[i])
.css()
.replace("rgb", "rgba")
.replace(")", ",1.0)"),
});
}
}
return newPalette;
}
function getRange(hexColor) {
const end = "#fff";
return [chroma(hexColor).darken(1.4).hex(), hexColor, end];
}
function getScale(hexColor, numOfColors) {
return chroma.scale(getRange(hexColor)).mode("lab").colors(numOfColors);
}
seedColors.js
export default [
{
paletteName: "Material UI Colors",
id: "material-ui-colors",
emoji: "🎨",
colors: [
{ name: "red", color: "#F44336" },
{ name: "pink", color: "#E91E63" },
{ name: "purple", color: "#9C27B0" },
{ name: "deeppurple", color: "#673AB7" },
{ name: "indigo", color: "#3F51B5" },
{ name: "blue", color: "#2196F3" },
{ name: "lightblue", color: "#03A9F4" },
{ name: "cyan", color: "#00BCD4" },
{ name: "teal", color: "#009688" },
{ name: "green", color: "#4CAF50" },
{ name: "lightgreen", color: "#8BC34A" },
{ name: "lime", color: "#CDDC39" },
{ name: "yellow", color: "#FFEB3B" },
{ name: "amber", color: "#FFC107" },
{ name: "orange", color: "#FF9800" },
{ name: "deeporange", color: "#FF5722" },
{ name: "brown", color: "#795548" },
{ name: "grey", color: "#9E9E9E" },
{ name: "bluegrey", color: "#607D8B" },
],
},
...
I’ve tried looking at the findPalette
and generatePalette
functions, at the palette component but I haven’t resulted in anything but this error.
2
Answers
Your issue is with
PaletteWrapper
Try the code above and see if it will throw that error
Issue
The issue is in the
generatePalette
where the code attempts to access properties of an undefinedstarterPalette
function argument.Solutions
You can resolve in several ways, here are a couple trivial suggestions:
Provide fallback initial value to
generatePalatte
function:Realize that
Array.prototype.find
potentially returnsundefined
if there are no matches, so it could return a defined fallback value.