質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

2回答

419閲覧

【Next.js】JSONから読み込むと『TypeError: Cannot read properties of undefined』が出る

a_teratail

総合スコア1

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

1クリップ

投稿2023/02/22 22:20

実現したいこと

  • JSONからTypeScriptにデータを読み込んで表示させたい

前提

Next.js/React TypeScript JSONを使ってWebサイトを作っています。
JSONからデータを読み込もうとした際に以下のエラーメッセージが発生しました。

発生している問題・エラーメッセージ

TypeError: Cannot read properties of undefined (reading 'h1')

該当のソースコード

TypeScript

1import styles from 'styles/keyword.module.css'; 2 3export function Keyword(props) { 4 5 const keyword = props.keyword; 6 7 return ( 8 <div className={styles.sideBySide}> 9 <h1>{keyword.h1}</h1> 10 {keyword.p.map((p, index) => ( 11 <p key={index} className={`${styles.icon} ${styles.iconText}`}> 12 {p} 13 </p> 14 ))} 15 </div> 16 ); 17} 18 19// Fetching data from the JSON file 20// import path from 'path' 21 22export async function getStaticProps() { 23 const filePath = path.join(process.cwd(), 'data.json'); 24 const res = await fetch(filePath); 25 const objectData = await res.json(); 26 27 return { 28 props: objectData.data 29 }; 30 31}

JSON

1{ 2 "data": { 3 "keyword": { 4 "h1": "be used to", 5 "p": [ 6 "助動詞", 7 "熟語" 8 ] 9 }, 10 "tips": [ 11 "発音に注意", 12 "be used to / get used to の違いに注意", 13 "used to 原形 / be used to -ing / be used to 原形 の違いに注意" 14 ], 15 "japanese": { 16 "be used to 名詞で「名詞に慣れている」" 17 }, 18 "english": { 19 "quote": "to have experienced something so that it no longer seems surprising, difficult, strange etc", 20 "source": "ロングマン現代英英辞典" 21 } 22 } 23}

試したこと

いろいろと調べたところ、JSONからデータをfetchするときに遅延が起きていてkeywordコンポーネントにデータが渡せていないんじゃないかというところまで現在仮説を立てました。

そして、遅延を回避するため、次のようなコードに修正しました。

TypeScript

1import { useEffect, useState } from 'react'; 2import styles from 'styles/keyword.module.css'; 3 4export function Keyword(props) { 5 const [keyword, setKeyword] = useState(null); 6 7 useEffect(() => { 8 async function fetchData() { 9 const response = await fetch('/data.json'); 10 const data = await response.json(); 11 setKeyword(data.data.keyword); 12 } 13 fetchData(); 14 }, []); 15 16 if (!keyword) { 17 return <div>Loading...</div>; 18 } 19 20 return ( 21 <div className={styles.sideBySide}> 22 <h1>{keyword.h1}</h1> 23 {keyword.p.map((p, index) => ( 24 <p key={index} className={`${styles.icon} ${styles.iconText}`}> 25 {p} 26 </p> 27 ))} 28 </div> 29 ); 30}

しかし、結果としては

TypeScript

1 if (!keyword) { 2 return <div>Loading...</div>; 3 }

の部分の「Loading...」が表示されるだけで、本来表示したい

TypeScript

1 <div className={styles.sideBySide}> 2 <h1>{keyword.h1}</h1> 3 {keyword.p.map((p, index) => ( 4 <p key={index} className={`${styles.icon} ${styles.iconText}`}> 5 {p} 6 </p> 7 ))} 8 </div>

は表示されない状況です。

補足情報(FW/ツールのバージョンなど)

{ "name": "nextdictionary", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", "@mui/icons-material": "^5.11.0", "@mui/material": "^5.11.8", "@next/font": "13.1.6", "@types/node": "18.11.18", "@types/react": "18.0.27", "@types/react-dom": "18.0.10", "eslint": "8.33.0", "eslint-config-next": "13.1.6", "next": "^13.1.7-canary.26", "react": "18.2.0", "react-dom": "18.2.0", "react-icons": "^4.7.1", "typescript": "4.9.5" } }

プログラミング初心者・はじめてのteratail利用ということで
至らない点があるかと思いますが
どうぞよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

import data from '../data.json';

を使ってJSONを読み込むことで解決しました!

解決後の全体のコードは以下のようになっています。

import styles from 'styles/keyword.module.css'; import data from '../data.json'; export function Keyword() { const keyword = data.data.keyword; return ( <div className={styles.sideBySide}> <h1>{keyword.h1}</h1> {keyword.p.map((p, index) => ( <p key={index} className={`${styles.icon} ${styles.iconText}`}> {p} </p> ))} </div> ); }

今回の学びは次の2点でした。

  • pagesの中にあるファイル以外ではgetStaticPropsは使えない。
  • fetchは外部のjsonなどを読み込むときに使うものなので、今回は使う必要はない。JSONファイルが同じリポジトリの中に入ってるので、importすればOK。

投稿2023/02/28 20:47

a_teratail

総合スコア1

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

fetch then の中で set でしょうか

tsx

1import React, { useState, useEffect } from 'react' 2 3const Fetch = () => { 4 5 const [posts, setPosts] = useState([]) 6 7 useEffect(() => { 8 fetch('https://jsonplaceholder.typicode.com/posts', { method: 'GET' }) 9 .then(res => res.json()) 10 .then(data => { 11 setPosts(data) 12 }) 13 }, []) 14 15 return ( 16 <div> 17 <ul> 18 { 19 posts.map(post => 20 <li key={ post.id } > { post.title } </li> 21 ) 22 } 23 </ul> 24 25 </div> 26 ) 27} 28 29export default Fetch;

投稿2023/02/23 03:47

yuma.inaura

総合スコア1453

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問