英文:
Getting id with useParams (react router dom v6.11.0
问题
我正在跟随Colt Steele的React课程。不幸的是,这门课程已经过时,所以我选择使用函数组件而不是基于类的组件。
目前,我遇到了一个我不理解的问题。我将展示我的代码和错误消息。
App.js
```jsx
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>
</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" },
],
},
//...
];
我尝试过查看findPalette
和generatePalette
函数以及调色板组件,但除了这个错误外,我还没有取得任何结果。
<details>
<summary>英文:</summary>
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.
```lang-none
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.
答案1
得分: 1
你的问题出在PaletteWrapper
:
const PaletteWrapper = () => {
const { id } = useParams();
const foundPalette = findPalette(id);
if (!foundPalette) throw new Error(`ID为${id}的调色板不存在。`);
const palette = generatePalette(foundPalette);
return <Palette palette={palette} />;
};
尝试使用上述代码,看看是否会抛出错误。
英文:
Your issue is with PaletteWrapper
const PaletteWrapper = () => {
const { id } = useParams();
const foundPalette = findPalette(id);
if(!foundPalette) throw new Error(`Palette with id: ${id} does not exits.`)
const palette = generatePalette(foundPalette);
return <Palette palette={palette} />;
};
Try the code above and see if it will throw that error
答案2
得分: 0
问题
问题出在 generatePalette
函数中,代码试图访问未定义的 starterPalette
函数参数的属性。
export function generatePalette(starterPalette) { // <-- undefined
let newPalette = {
paletteName: starterPalette.paletteName, // <-- throws error
id: starterPalette.id,
emoji: starterPalette.emoji,
colors: {},
};
...
解决方案
您可以通过多种方式解决这个问题,以下是一些简单的建议:
-
为
generatePalette
函数提供默认初始值:... import seedColors from "./seedColors"; ... export function generatePalette(starterPalette = seedColors[0]) { const newPalette = { paletteName: starterPalette.paletteName, id: starterPalette.id, emoji: starterPalette.emoji, colors: {}, }; ...
-
请注意,如果没有匹配项,
Array.prototype.find
可能会返回undefined
,因此它可以返回一个定义的备用值。const findPalette = (id) => { return seedColors.find((palette) => palette.id === id) ?? seedColors[0]; };
英文:
Issue
The issue is in the generatePalette
where the code attempts to access properties of an undefined starterPalette
function argument.
export function generatePalette(starterPalette) { // <-- undefined
let newPalette = {
paletteName: starterPalette.paletteName, // <-- throws error
id: starterPalette.id,
emoji: starterPalette.emoji,
colors: {},
};
...
Solutions
You can resolve in several ways, here are a couple trivial suggestions:
-
Provide fallback initial value to
generatePalatte
function:... import seedColors from "./seedColors"; ... export function generatePalette(starterPalette = seedColors[0]) { const newPalette = { paletteName: starterPalette.paletteName, id: starterPalette.id, emoji: starterPalette.emoji, colors: {}, }; ...
-
Realize that
Array.prototype.find
potentially returnsundefined
if there are no matches, so it could return a defined fallback value.const findPalette = (id) => { return seedColors.find((palette) => palette.id === id) ?? seedColors[0]; };
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论