使用useParams获取id(react router dom v6.11.0)

huangapple go评论72阅读模式
英文:

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" },
    ],
  },
  //...
];

我尝试过查看findPalettegeneratePalette函数以及调色板组件,但除了这个错误外,我还没有取得任何结果。


<details>
<summary>英文:</summary>
I am following Colt Steele&#39;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&#39;t understand. I&#39;ll show my code and the error message. 
```lang-none
colorHelpers.js:7  Uncaught TypeError: Cannot read properties of undefined (reading &#39;paletteName&#39;)
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 &quot;react-router-dom&quot;;

import { generatePalette } from &quot;./colorHelpers&quot;;
import Palette from &quot;./Palette&quot;;
import seedColors from &quot;./seedColors&quot;;

function App() {
  const findPalette = (id) =&gt; {
    const palette = seedColors.find((palette) =&gt; palette.id === id);
    console.log(palette);
    return palette;
  };

  const PaletteWrapper = () =&gt; {
    const { id } = useParams();

    const palette = generatePalette(findPalette(id));

    return &lt;Palette palette={palette} /&gt;;
  };

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;Routes&gt;
        &lt;Route path=&quot;/&quot; element={&lt;h1&gt;Welcome Home&lt;/h1&gt;} /&gt;
        &lt;Route path=&quot;/palette/:id&quot; element={&lt;PaletteWrapper /&gt;} /&gt;
      &lt;/Routes&gt;

      {/* &lt;Palette palette={generatePalette(seedColors[3])} /&gt; */}
    &lt;/div&gt;
  );
}

export default App;

Palette.js

import { useState } from &quot;react&quot;;
import ColorBox from &quot;./ColorBox&quot;;
import { Navbar } from &quot;./Navbar&quot;;
import &quot;./Palette.css&quot;;

const Palette = (props) =&gt; {
  const [level, setLevel] = useState(500);
  const [format, setFormat] = useState(&quot;hex&quot;);

  const changeFormat = (format) =&gt; {
    setFormat(format);
  };

  const changeLevel = (newLevel) =&gt; {
    setLevel(newLevel);
  };

  const { colors, paletteName, emoji } = props.palette;

  const colorBoxes = colors[level].map((color) =&gt; (
    &lt;ColorBox key={color.name} background={color[format]} name={color.name} /&gt;
  ));

  return (
    &lt;div className=&quot;Palette&quot;&gt;
      &lt;Navbar
        level={level}
        changeLevel={changeLevel}
        changeFormat={changeFormat}
        format={format}
      /&gt;
      &lt;div className=&quot;Palette-colors&quot;&gt;{colorBoxes}&lt;/div&gt;
      &lt;div className=&quot;Palette-footer&quot;&gt;
        {paletteName}
        &lt;span className=&quot;emoji&quot;&gt;{emoji}&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
};

export default Palette;

colorHelpers.js

import chroma from &quot;chroma-js&quot;;

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, &quot;-&quot;),
        hex: scale[i],
        rgb: chroma(scale[i]).css(),
        rgba: chroma(scale[i])
          .css()
          .replace(&quot;rgb&quot;, &quot;rgba&quot;)
          .replace(&quot;)&quot;, &quot;,1.0)&quot;),
      });
    }
  }
  return newPalette;
}

function getRange(hexColor) {
  const end = &quot;#fff&quot;;
  return [chroma(hexColor).darken(1.4).hex(), hexColor, end];
}

function getScale(hexColor, numOfColors) {
  return chroma.scale(getRange(hexColor)).mode(&quot;lab&quot;).colors(numOfColors);
}

seedColors.js

export default [
  {
    paletteName: &quot;Material UI Colors&quot;,
    id: &quot;material-ui-colors&quot;,
    emoji: &quot;&#127912;&quot;,
    colors: [
      { name: &quot;red&quot;, color: &quot;#F44336&quot; },
      { name: &quot;pink&quot;, color: &quot;#E91E63&quot; },
      { name: &quot;purple&quot;, color: &quot;#9C27B0&quot; },
      { name: &quot;deeppurple&quot;, color: &quot;#673AB7&quot; },
      { name: &quot;indigo&quot;, color: &quot;#3F51B5&quot; },
      { name: &quot;blue&quot;, color: &quot;#2196F3&quot; },
      { name: &quot;lightblue&quot;, color: &quot;#03A9F4&quot; },
      { name: &quot;cyan&quot;, color: &quot;#00BCD4&quot; },
      { name: &quot;teal&quot;, color: &quot;#009688&quot; },
      { name: &quot;green&quot;, color: &quot;#4CAF50&quot; },
      { name: &quot;lightgreen&quot;, color: &quot;#8BC34A&quot; },
      { name: &quot;lime&quot;, color: &quot;#CDDC39&quot; },
      { name: &quot;yellow&quot;, color: &quot;#FFEB3B&quot; },
      { name: &quot;amber&quot;, color: &quot;#FFC107&quot; },
      { name: &quot;orange&quot;, color: &quot;#FF9800&quot; },
      { name: &quot;deeporange&quot;, color: &quot;#FF5722&quot; },
      { name: &quot;brown&quot;, color: &quot;#795548&quot; },
      { name: &quot;grey&quot;, color: &quot;#9E9E9E&quot; },
      { name: &quot;bluegrey&quot;, color: &quot;#607D8B&quot; },
    ],
  },
  ...

使用useParams获取id(react router dom v6.11.0)

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 = () =&gt; {
const { id } = useParams();
const foundPalette = findPalette(id);
if(!foundPalette) throw new Error(`Palette with id: ${id} does not exits.`)
const palette = generatePalette(foundPalette);
return &lt;Palette palette={palette} /&gt;;
};

Try the code above and see if it will throw that error

答案2

得分: 0

问题

问题出在 generatePalette 函数中,代码试图访问未定义的 starterPalette 函数参数的属性。

export function generatePalette(starterPalette) { // &lt;-- undefined
  let newPalette = {
    paletteName: starterPalette.paletteName, // &lt;-- throws error
    id: starterPalette.id,
    emoji: starterPalette.emoji,
    colors: {},
  };

  ...

解决方案

您可以通过多种方式解决这个问题,以下是一些简单的建议:

  1. generatePalette 函数提供默认初始值:

    ...
    import seedColors from &quot;./seedColors&quot;;
    ...
    
    export function generatePalette(starterPalette = seedColors[0]) {
      const newPalette = {
        paletteName: starterPalette.paletteName,
        id: starterPalette.id,
        emoji: starterPalette.emoji,
        colors: {},
      };
    
      ...
    
  2. 请注意,如果没有匹配项,Array.prototype.find 可能会返回 undefined,因此它可以返回一个定义的备用值。

    const findPalette = (id) =&gt; {
      return seedColors.find((palette) =&gt; 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) { // &lt;-- undefined
  let newPalette = {
    paletteName: starterPalette.paletteName, // &lt;-- throws error
    id: starterPalette.id,
    emoji: starterPalette.emoji,
    colors: {},
  };

  ...

Solutions

You can resolve in several ways, here are a couple trivial suggestions:

  1. Provide fallback initial value to generatePalatte function:

    ...
    import seedColors from &quot;./seedColors&quot;;
    ...
    
    export function generatePalette(starterPalette = seedColors[0]) {
      const newPalette = {
        paletteName: starterPalette.paletteName,
        id: starterPalette.id,
        emoji: starterPalette.emoji,
        colors: {},
      };
    
      ...
    
  2. Realize that Array.prototype.find potentially returns undefined if there are no matches, so it could return a defined fallback value.

    const findPalette = (id) =&gt; {
      return seedColors.find((palette) =&gt; palette.id === id) ?? seedColors[0];
    };
    

huangapple
  • 本文由 发表于 2023年6月11日 22:22:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76450923.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定