1. ホーム
  2. javascript

[解決済み] Reactの「TypeError: results.map is not a function」を修正する方法。

2022-03-03 22:36:57

質問

function Results(props) {
  var results = props.results;
  return (
    <>
      <table>
        <thead>
          <tr>
            <th>Book Name</th>
            <th>Author</th>
            <th>S.no</th>
            <th>Series Name</th>
            <th>Type</th>
            <th>Genre</th>
            <th>Kindle/Real</th>
          </tr>
        </thead>
        <tbody>
          {results.map(result => {
            return (
              <tr key={result.name}>
                <td>{result.name}</td>
                <td>{result.author}</td>
                <td>{result.sno}</td>
                <td>{result.series}</td>
                <td>{result.type}</td>
                <td>{result.genre}</td>
                <td>{result.kindeReal}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </>
  );
}

上記のcomコンポーネントをレンダリングしようとすると、エラーが発生します。

TypeError: results.map は関数ではありません。

results変数は、オブジェクトの配列のようなものです。

[{"type":1},{"type":0},{"type":2}]

しかし、.map関数を使うと、エラーが返ってきます 明らかに配列なのに、なぜ使えないのでしょうか?

console.log(results)の出力です。

[{"Book_Name":"Time Riders","Author":"Alex Scarrow","S_no":1,"Series_Name":"Time Riders","Fiction_Non_fiction_Companion_Prequel":"Fiction","Genre":"Sci-fi/Mystery/Thriller","Kindle_Real":"Real"},{"Book_Name":"Day of the Predator ","Author":"Alex Scarrow","S_no":2,"Series_Name":"Time Riders","Fiction_Non_fiction_Companion_Prequel":"Fiction","Genre":"Sci-fi/Mystery/Thriller","Kindle_Real":"Real"},{"Book_Name":"The Doomsday Code","Author":"Alex Scarrow","S_no":3,"Series_Name":"Time Riders","Fiction_Non_fiction_Companion_Prequel":"Fiction","Genre":"Sci-fi/Mystery/Thriller","Kindle_Real":"Real"},{"Book_Name":"The Eternal War","Author":"Alex Scarrow","S_no":4,"Series_Name":"Time Riders","Fiction_Non_fiction_Companion_Prequel":"Fiction","Genre":"Sci-fi/Mystery/Thriller","Kindle_Real":"Real"},{"Book_Name":"Gates of Rome","Author":"Alex Scarrow","S_no":5,"Series_Name":"Time Riders","Fiction_Non_fiction_Companion_Prequel":"Fiction","Genre":"Sci-fi/Mystery/Thriller","Kindle_Real":"Real"},{"Book_Name":"City of Shadows","Author":"Alex Scarrow","S_no":6,"Series_Name":"Time Riders","Fiction_Non_fiction_Companion_Prequel":"Fiction","Genre":"Sci-fi/Mystery/Thriller","Kindle_Real":"Real"},{"Book_Name":"The Pirate Kings","Author":"Alex Scarrow","S_no":7,"Series_Name":"Time Riders","Fiction_Non_fiction_Companion_Prequel":"Fiction","Genre":"Sci-fi/Mystery/Thriller","Kindle_Real":"Real"},{"Book_Name":"The Mayan Prophecy","Author":"Alex Scarrow","S_no":8,"Series_Name":"Time Riders","Fiction_Non_fiction_Companion_Prequel":"Fiction","Genre":"Sci-fi/Mystery/Thriller","Kindle_Real":"Real"},{"Book_Name":"The Infinity Cage","Author":"Alex Scarrow","S_no":9,"Series_Name":"Time Riders","Fiction_Non_fiction_Companion_Prequel":"Fiction","Genre":"Sci-fi/Mystery/Thriller","Kindle_Real":"Real"}]

私には配列に見えるのですが。では、なぜ配列ではないのでしょうか?

これが親コンポーネントです。

import React from "react";
import Results from "./results";

function ResultsRenderer(props) {
  if (props.status === true) {
    return <Results results={props.results} />;
  } else {
    return <>{"No"}</>;
  }
}

export default ResultsRenderer;

ResultsRendererの親コンポーネントです。

import React, { useState } from "react";
import { useEffect } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Form from "./searcherFormDumb";
import { toast } from "react-toastify";
import ResultsRenderer from "./resultsRenderer";

function Searcher() {
  const [answer, setAnswer] = useState(["Empty", false]);
  const [book, setBook] = useState({
    name: "",
    author: "",
    sno: null,
    series: "",
    type: "",
    genre: "",
    kindleReal: ""
  });
  const defaultState = {
    name: "",
    author: "",
    sno: null,
    series: "",
    type: "",
    genre: "",
    kindleReal: ""
  };

  function handleChange(event) {
    const updatedBook = { ...book, [event.target.name]: event.target.value };
    setBook(updatedBook);
  }

  function handleSubmit(event) {
    event.preventDefault();
    var changed = {};
    function populateChanged(now, old, title, temp) {
      if (now !== old) {
        temp[title] = now;
        return temp;
      } else {
        return temp;
      }
    }
    changed = populateChanged(
      book.name,
      defaultState.name,
      "Book_Name",
      changed
    );
    changed = populateChanged(
      book.author,
      defaultState.author,
      "Author",
      changed
    );
    changed = populateChanged(book.sno, defaultState.sno, "S_no", changed);
    changed = populateChanged(
      book.series,
      defaultState.series,
      "Series_Name",
      changed
    );
    changed = populateChanged(
      book.type,
      defaultState.type,
      "Fiction_Non_fiction_Companion_Prequel",
      changed
    );
    changed = populateChanged(book.genre, defaultState.genre, "Genre", changed);
    changed = populateChanged(
      book.kindleReal,
      defaultState.kindleReal,
      "Kindle_Real",
      changed
    );
    var temp_string = "";
    var key = "";
    var value = "";
    var temp_string_list = [];
    //debugger;
    for (var i = 0; i < Object.keys(changed).length; i++) {
      //debugger;
      key = Object.keys(changed)[i];
      value = changed[key];
      if (i !== Object.keys(changed).length - 1) {
        temp_string = `${key} = "${value}" AND `;
      } else if (i === Object.keys(changed).length - 1) {
        temp_string = `${key} = "${value}"`;
      }
      temp_string_list.push(temp_string);
      //debugger;
      temp_string = "";
      key = "";
      value = "";
    }

    var sql_t = temp_string_list.join("");
    var sql_tt = "SELECT * FROM books_catalouge WHERE ";
    var sql = sql_tt + sql_t;
    toast.success(sql);

    var request = new XMLHttpRequest();
    var jsql = JSON.stringify(sql);
    request.onreadystatechange = function() {
      //debugger;
      if (this.readyState == 4 && this.status == 200) {
        setAnswer([this.responseText, true]);
        console.log(`${answer}`);
      }
    };
    request.open(
      "GET",
      "http://localhost:3001/retrieve_books" + "?msg=" + jsql,
      true
    );
    request.send(jsql);
    console.log("This is the END");
    console.log(`${answer}`);
  }

  return (
    <>
      <Form book={book} onChange={handleChange} onSubmit={handleSubmit} />
      <br />
      <ResultsRenderer status={answer[1]} results={answer[0]} />
    </>
  );
}

export default Searcher;

NodeJSも必要なら教えてください。私はデータを取得するためにSQLを使用しており、それがNodeJSを必要とする理由です。私のコードが少し奇妙であれば申し訳ありません。

ありがとうございました。

どのように解決するのですか?

機能 map() でのみ使用可能です。 配列 . このような場合、次のようになります。 props.results が配列になっていないか、まだ設定されていません (これは Axios などでデータを取得している場合に起こる可能性があります)。

関数の最初にこのようなものを置くことをお勧めします。

if (!props.results) return 'no data';
if (!Array.isArray(props.results)) return 'results are not array'


明確化後

に対する応答が得られます。 onreadystatechange リクエストは通常JSONまたはXMLで提供されます。あなたの答えは、文字列化されたJSONだと思います。試しに JSON.parse(response) JSONの場合、または (new DOMParser()).parseFromString(response,"text/xml") はXMLの場合です。

あなたのコンポーネントでは、次のようになります。

request.onreadystatechange = function() {
   (this.readyState == 4 && this.status == 200)
      && setAnswer([JSON.parse(this.responseText), true]);
};