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

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

新規登録して質問してみよう
ただいま回答率
85.46%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

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

React.js

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

Q&A

解決済

2回答

1587閲覧

TypeError: Cannot read property 'map' of undefined というエラーが出る。

yaaasuuu

総合スコア5

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

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

React.js

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

0グッド

0クリップ

投稿2020/02/11 18:25

こちらのサイトの内容をTypeScriptで書いているのですが、エラーの解消方法を教えていただきたいです。

エディタ上でのエラーは出ていないのですがブラウザ上でエラーが出ています。
ブラウザ上のエラー

インターネットでこのエラーを調べるとタイプミスであったり、値が与えられてなかったりしていたのですが自分で見る限り見つけることはできませんでした。下にコードを貼っておきます。

TypeScript

1 2/*Search.tsx*/ 3 4import React, { useState } from 'react'; 5 6export interface SearchProps { 7 search: (searchValue: string) => void 8} 9 10const Search = (props: SearchProps) => { 11 const [searchValue, setSearchValue] = useState(''); 12 13 const handleSearchInputChanges = (e: React.ChangeEvent<HTMLInputElement>) => { 14 setSearchValue(e.target.value); 15 }; 16 17 const resetInputField = () => { 18 setSearchValue(''); 19 }; 20 21 const callSearchFunction = (e: React.MouseEvent<HTMLInputElement, MouseEvent>) => { 22 e.preventDefault(); 23 props.search(searchValue); 24 resetInputField(); 25 }; 26 27 return ( 28 <form className='search'> 29 <input 30 value={searchValue} 31 onChange={handleSearchInputChanges} 32 type="text" 33 /> 34 <input onClick={callSearchFunction} value='SEARCH' type="submit" /> 35 </form> 36 ); 37 38}; 39 40export default Search;

TypeScript

1 2/*Movie.tsx*/ 3 4import React from 'react'; 5 6const DEFAULT_PLACEHOLDER_IMAGE = 'https://m.media-amazon.com/images/M/MV5BMTczNTI2ODUwOF5BMl5BanBnXkFtZTcwMTU0NTIzMw@@._V1_SX300.jpg'; 7 8export interface MovieObj { 9 Poster: string, 10 Title: string, 11 Year: number, 12} 13 14const Movie: React.FC<{ movie: MovieObj }> = ({ movie }) => { 15 const poster = 16 movie.Poster === 'N/A' 17 ? DEFAULT_PLACEHOLDER_IMAGE 18 : movie.Poster; 19 20 return ( 21 <div className="movie"> 22 <h2>{movie.Title}</h2> 23 <div> 24 <img 25 width="200" 26 src={poster} 27 alt={`The movie titled: ${movie.Title}`} 28 /> 29 </div> 30 <p>({movie.Year})</p> 31 </div> 32 ); 33}; 34 35export default Movie;

TypeScript

1 2/*App.tsx*/ 3 4import React, { useEffect, useReducer } from 'react'; 5import '../App.css'; 6import Header from './Header'; 7// eslint-disable-next-line no-unused-vars 8import Movie, { MovieObj } from './Movie'; 9import Search from './Search'; 10 11const MOVIE_API_URL = 'http://www.omdbapi.com/?i=tt3896198&apikey=db671368'; 12 13 14interface ISearchMoviesRequest { 15 type: 'SEARCH_MOVIES_REQUEST' 16} 17 18interface ISearchMoviesSuccess { 19 type: 'SEARCH_MOVIES_SUCCESS', 20 payload: MovieObj[] 21} 22 23interface ISearchMoviesFailure { 24 type: 'SEARCH_MOVIES_FAILURE', 25 error: string 26} 27 28type IActions = 29 | ISearchMoviesRequest 30 | ISearchMoviesSuccess 31 | ISearchMoviesFailure; 32 33interface IState { 34 loading: boolean, 35 movies: MovieObj[], 36 errorMessage: string | null 37} 38 39const initialState: IState = { 40 loading: true, 41 movies: [], 42 errorMessage: null 43}; 44 45const reducer = (state: IState, action: IActions): IState => { 46 switch (action.type) { 47 case 'SEARCH_MOVIES_REQUEST': 48 return { 49 ...state, 50 loading: true, 51 errorMessage: null 52 }; 53 case 'SEARCH_MOVIES_SUCCESS': 54 return { 55 ...state, 56 loading: false, 57 movies: action.payload 58 }; 59 case 'SEARCH_MOVIES_FAILURE': 60 return { 61 ...state, 62 loading: false, 63 errorMessage: action.error 64 }; 65 default: 66 return state; 67 } 68}; 69 70const App = () => { 71 const [state, dispatch] = useReducer(reducer, initialState); 72 73 useEffect(() => { 74 75 fetch(MOVIE_API_URL) 76 .then(response => response.json()) 77 .then(jsonResponse => { 78 79 dispatch({ 80 type: 'SEARCH_MOVIES_SUCCESS', 81 payload: jsonResponse.Search 82 }); 83 }); 84 }, []); 85 86 const search = (searchValue: string): void => { 87 dispatch({ 88 type: 'SEARCH_MOVIES_REQUEST' 89 }); 90 91 fetch(`http://www.omdbapi.com/?i=${searchValue}&apikey=db671368`) 92 .then(response => response.json()) 93 .then(jsonResponse => { 94 if (jsonResponse.response === 'True') { 95 dispatch({ 96 type: 'SEARCH_MOVIES_SUCCESS', 97 payload: jsonResponse.Search 98 }); 99 } else { 100 dispatch({ 101 type: 'SEARCH_MOVIES_FAILURE', 102 error: jsonResponse.Error 103 }); 104 } 105 }); 106 }; 107 108 const { movies, errorMessage, loading } = state; 109 110 return ( 111 <div className="App"> 112 <Header text="HOOKED" /> 113 <Search search={search} /> 114 <p className="App-intro">Sharing a few of our favourite movies</p> 115 <div className="movies"> 116 {loading && !errorMessage 117 ? (<span>loading... </span>) 118 : errorMessage 119 ? (<div className="errorMessage">{errorMessage}</div>) 120 : (movies.map((movie: MovieObj, index: number) => ( 121 <Movie key={`${index}-${movie.Title}`} movie={movie} /> 122 )) 123 )} 124 </div> 125 </div> 126 ); 127}; 128 129export default App;

1つ自信がない部分がApp.tsxconst App = () => {}でのfetch内で、APIを使ったことがなくかつTypeScriptも初学習であるため合っているのかわからないです。(そこでmoviesに値が渡されていない?)

よろしくお願いいたします。

環境 React: 16.12.0 TypeScript: 3.7.5

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

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

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

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

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

guest

回答2

0

moviesがundefinedかと思います。
console.logでmoviesが来ているか確認してみてください!

ちなみに、この記事がApiからデータを取得する方法としてはわかりやすかったですよ!

投稿2020/02/11 19:21

amedama

総合スコア37

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

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

yaaasuuu

2020/02/11 21:58

仰る通りundifinedとなっていました... 記事ありがとうございます!もう少し頑張ってみます!
guest

0

自己解決

結論からいうとAPIの仕様を詳しく見ていなかったのが原因でした。

コードの変更部分は2つあります。

1 OMDbAPIのUsageを見ると、Searchによって検索するには元のコードのURL部分を変更する必要がありました。

TypeScript

1/*App.tsx*/ 2... 3// 8行目 4const MOVIE_API_URL = 'http://www.omdbapi.com/?i=tt3896198&apikey=db671368; 5 6...

から

TypeScript

1// パラメータiをsとする。(XXXは検索したい文字列) 2const MOVIE_API_URL = 'http://www.omdbapi.com/?s=XXX&apikey=db671368;

としました。

2 次にAPIから返ってくるjsonファイルを見てみると、

json

1{ 2 "Search": [ 3 {"Title":"hoge","Year":"2000","Poster":"http://hoge "}, 4 {"Title":"foo","Year":"1900","Poster":"http://foo "} 5 ], 6 "Response":"True" 7}

といったように、Responseが返ってきます。(コードは整形してます)
しかしresponseと書いてしまっていたため何が来てもelse部に入ってしまいmoviesが空となっていました。

TypeScript

1fetch(`http://www.omdbapi.com/?apikey=db671368&s=${searchValue}`) 2 .then(response => response.json()) 3 .then(jsonResponse => { 4 5 // この部分が response でなく Response 6 if (jsonResponse.response === 'True') { 7 8 dispatch({ 9 type: 'SEARCH_MOVIES_SUCCESS', 10 payload: jsonResponse.Search 11 }); 12 } else { 13 dispatch({ 14 type: 'SEARCH_MOVIES_FAILURE', 15 error: jsonResponse.Error 16 }); 17 } 18 });

しっかりと仕様を読むべきでした...
回答してくださったamedama様の貼ってくださった記事も、axiosを用いたAPIの扱いがわかりやすく書いてあったので全体の流れを整理して考えることができました。(useReducerと一緒に使う練習をしていきたいです)。ありがとうございました。

投稿2020/02/12 13:58

yaaasuuu

総合スコア5

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問