错误在下一步的第13步,使用解构参数时出现。

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

Error at building in next 13 with params destructuration

问题

当我使用Next 13.1.2运行npm run build时,在我的Words组件中,当我尝试将单词从本地JSON的数组分配给一个常量时,我遇到了以下错误:

TypeError: Cannot read properties of undefined (reading '[difficulty]') 

这是我第一次使用Next框架,而这个错误仅在我运行Next的构建命令时才会出现,但在开发环境中,它可以正常工作而不会抛出任何错误。我知道这是因为当它从参数中解构出级别和难度时,而不是只接收类似于'easy'或级别字符串如'1'时,我得到了这种奇怪的字符串,如%5Bdifficulty%5D或%Blevel%5D。我不知道为什么会发生这种情况。

这是我接收URL参数的地方,URL为/levels/[level]/[difficulty]:

/levels/[level]/[difficulty]/page.jsx
export default function page({ params }) {
  const { level, difficulty } = params;

  return (
    <div className='level-container'>
      <BackButton path={`/levels/${level}`} />
      <Words level={parseInt(level)} difficulty={difficulty} />
    </div>
  );
}

这是引发错误的Words组件:

//@components/GameComponents/Words.jsx
import SingleWord from './SingleWord';
import levelsData from '@/data/levels.json';
import WordsProvider from '@/contexts/WordsContext';
import { UseLevels } from '@/contexts/LevelsContext';
import LevelUnlocked from '../LevelUnlocked';

export default function Words({ level, difficulty }) {
  const words = levelsData[level - 1][difficulty];
  const { newLevelUnlocked } = UseLevels;

  return (
    <WordsProvider>
      <div className="words-container">
        {words.map((word) => (
          <SingleWord
            word={word}
            key={word}
            level={level}
            difficulty={
              difficulty === 'easy' ? 1 : difficulty === 'medium' ? 2 : 3
            }
          />
        ))}
        {newLevelUnlocked && <LevelUnlocked />}{''}
        {/*Alert the user that a new level has been unlocked*/}
      </div>
    </WordsProvider>
  );
}

最后,这是我的JSON文件:

//data/levels.json
[
  {
    "index": 0,
    "level" : 1,
    "easy" : ["Work", "Play", "Milk", "Game", "Year"],
    "medium" : ["Space", "Apple", "Water", "Beach", "Arrow"],
    "hard": ["Finger", "Little", "Combat", "Cloudy", "Health"]
  },
  {
    "index": 1,
    "level" : 2,
    "easy" : ["Fist", "Stop", "Tree", "Ride", "Iron"],
    "medium" : ["Ocean", "Train", "Write", "Close", "Civil"],
    "hard": ["Dolphin", "Emotion", "Phrases", "Strings", "Accords"]
  },
  {
    "index": 2,
    "level" : 3,
    "easy" : ["Jump", "Lost", "True", "Mind", "Rude"],
    "medium" : ["Grass", "Bunny", "Party", "Rugby", "Storm"],
    "hard": ["Doctor", "Little", "Accord", "Sponge", "Suffix"]
  },
  {
    "index": 3,
    "level" : 4,
    "easy" : ["Brown", "Civil", "Gests", "Sleep", "Clock"],
    "medium" : ["Hunger", "Pencil", "Shield", "Ginger", "Travel"],
    "hard": ["Academy", "Elegant", "Scholar", "Miracle", "Victory"]
  }
]

一开始,我以为问题可能是因为我将字符串作为级别属性传递,而不是数字,然后我将其转换为整数,但它仍然不起作用。我还尝试在构建中像这样记录难度:

levelsData[0][difficulty]

它似乎正确地记录在控制台中,所以问题应该与我在page.jsx组件中获取的级别和难度参数有关。

英文:

I'm getting this error when I run npm run build with next 13.1.2 in my Words component when I try to asign to a const the words from an array of a local json.

TypeError: Cannot read properties of undefined (reading '%5Bdifficulty%5D') 

I'm using for the first time the next framework, and this error only shows when I run the build command of next, but in development it works without throwing any error.I know that is because when it destructures the level and the difficulty from the params instead of recieving for example just 'easy' or the level string like '1' I'm getting this strange string like %5Bdifficulty%5D or %Blevel%5D . I don't know why this could be happening.

This is where I receive the params of the url that is /levels/[level]/[difficulty]

\levels\[level]\[difficulty]\page.jsx
export default function page({ params }) {
  const { level, difficulty } = params;

  return (
    <div className='level-container'>
      <BackButton path={`/levels/${level}`} />
      <Words level={parseInt(level)} difficulty={difficulty} />
    </div>
  );
}

And this is the Words component where I get the error.

//@components/GameComponents/Words.jsx
import SingleWord from './SingleWord';
import levelsData from '@/data/levels.json';
import WordsProvider from '@/contexts/WordsContext';
import { UseLevels } from '@/contexts/LevelsContext';
import LevelUnlocked from '../LevelUnlocked';

export default function Words({ level, difficulty }) {
  const words = levelsData[level - 1][difficulty];
  const { newLevelUnlocked } = UseLevels;

  return (
    <WordsProvider>
      <div className="words-container">
        {words.map((word) => (
          <SingleWord
            word={word}
            key={word}
            level={level}
            difficulty={
              difficulty === 'easy' ? 1 : difficulty === 'medium' ? 2 : 3
            }
          />
        ))}
        {newLevelUnlocked && <LevelUnlocked />}{' '}
        {/*Alert the user that a new level has been unlocked*/}
      </div>
    </WordsProvider>
  );
}

And finally this is my json file.

//data/levels.json
[
  {
    "index": 0,
    "level" : 1,
    "easy" : ["Work", "Play", "Milk", "Game", "Year"],
    "medium" : ["Space", "Apple", "Water", "Beach", "Arrow"],
    "hard": ["Finger", "Little", "Combat", "Cloudy", "Health"]
  },
  {
    "index": 1,
    "level" : 2,
    "easy" : ["Fist", "Stop", "Tree", "Ride", "Iron"],
    "medium" : ["Ocean", "Train", "Write", "Close", "Civil"],
    "hard": ["Dolphin", "Emotion", "Phrases", "Strings", "Accords"]
  },
  {
    "index": 2,
    "level" : 3,
    "easy" : ["Jump", "Lost", "True", "Mind", "Rude"],
    "medium" : ["Grass", "Bunny", "Party", "Rugby", "Storm"],
    "hard": ["Doctor", "Little", "Accord", "Sponge", "Suffix"]
  },
  {
    "index": 3,
    "level" : 4,
    "easy" : ["Brown", "Civil", "Gests", "Sleep", "Clock"],
    "medium" : ["Hunger", "Pencil", "Shield", "Ginger", "Travel"],
    "hard": ["Academy", "Elegant", "Scholar", "Miracle", "Victory"]
  }
]

At the first I thought that could have been because I was passing as level prop a string instead of number, then I converted it into an integer but it doesn't work. I also tried to console log in the build a difficulty like this:
levelsData[0][difficulty]

And it seems to console log correctly, so the problem is with the level and difficulty params that I get in the page.jsx component I suppose.

答案1

得分: 0

**//levels/level/[level]/[difficulty]/page.jsx**

由于我是 Next 框架的新手我不知道在进行静态站点生成时需要生成静态参数因此我需要在构建时使用 **generateStaticParams** 函数创建这些参数因此我在这个组件中添加了 Next.js 13 的这个保留函数

    export async function generateStaticParams () {
      const difficulties = ['easy', 'medium', 'hard']
      return difficulties.map(diff => levelsData.map(lvl => ({
        level: lvl.level.toString(),
        difficulty: diff
      }))).flat()
    }

通过这种方式我为每个级别创建了一个站点并为每个级别包含所有的难度我决定采取自下而上的方式
英文:

//levels/level/[level]/[difficulty]/page.jsx

Since I'm new in the Next framework world I didn't know about that you need to generate your static parameters when you want to have static site generation. So I need to create at build time that parameters with generateStaticParams. So I added this reserved function of next js 13 in this component.

export async function generateStaticParams () {
  const difficulties = ['easy', 'medium', 'hard']
  return difficulties.map(diff => levelsData.map(lvl => ({
    level: lvl.level.toString(),
    difficulty: diff
  }))).flat()
}

So in this way I create a site for each level, and each level with all the difficulties. I decided to go for the bottom up way.

huangapple
  • 本文由 发表于 2023年2月14日 02:57:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75440142.html
匿名

发表评论

匿名网友

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

确定