TypeError undefined is not a function (near...map)

TypeError undefined is not a function (near...map)

我正在尝试实现一个简单的过滤器部分来过滤我正在映射的数组的结果,以及当我的函数找到正确答案并且应该更改状态时,结果即使基于相同的状态,也不会重新渲染。 也许它来自我映射结果的方式,因为我的过滤器只返回一个匹配并且应该由默认显示所有结果的相同映射函数显示。这真的很烦人,因为我知道我的过滤器函数正在返回正确的答案,但我无法让它显示在页面上。

整个网站崩溃了。 请帮忙!

import React, { useState, useEffect } from "react";
import { useAuth0 } from "@auth0/auth0-react";
import "../style/content.css";
import LoginButton from "./LoginButton";
import Modal from "./Modal";
var axios = require("axios").default;

const StockContent = () => {
  const { isAuthenticated } = useAuth0();
  const [datas, setDatas] = useState([]);
  const [selectFil, setSelectFil] = useState("");
  const [isOpen, setIsOpen] = useState(false);

  useEffect(() => {
    var options = {
      method: "GET",
      url: "https://run.mocky.io/v3/6daa5c5c-4c1b-4bce-8596-c604fa9f52dc",
      params: { modules: "defaultKeyStatistics,assetProfile" }
    };

    axios
      .request(options)
      .then(function (response) {
        var results = response.data.marketSummaryResponse.result;
        setDatas(results);
        console.log(results);
      })
      .catch(function (error) {
        console.error(error);
      });
  }, []);

  const handleChange = (e) => {
    debugger;
    setSelectFil(e.target.value);
  };

  const findMatch = (selected) => {
    debugger;
    const matchData = datas.find((data) => data.exchange === selected);
    setDatas(matchData);
  };

  return (
    <>
      {isAuthenticated ? (
        <>
          <div className="title">
            <h1>
              Market Summary <i class="fas fa-chart-pie"></i>
            </h1>
          </div>
          <div className="filter_sec">
            <h3>Search By Filter</h3>
            <br></br>
            <select name="exchange" id="stock" value={selectFil} onChange={handleChange}>
              {datas.map((data, i) => {
                return <option>{data.exchange}</option>;
              })}
            </select>
            <select name="market" id="mark">
              {datas.map((data, i) => {
                return <option value="market">{data.market}</option>;
              })}
            </select>
            <br />
            <button onClick={() => findMatch(selectFil)}>Filter</button>
          </div>
          <div className="card_content">
            {datas &&
              datas.length > 0 &&
              datas.map((data, i) => {
                return (
                  <div className="card_style" key={data}>
                    <div className="card_info">
                      <div className="logo_sn">
                        <h4 id="stock_sn">{data.shortName}</h4>
                        <div className="logo"></div>
                      </div>
                      <div className="card_info_det">
                        <h4>Exchange : {data.exchange}</h4>
                        <h4>Market : {data.market}</h4>
                        <h4>TimeZone : {data.exchangeTimezoneName}</h4>
                        <h4>Change Rate : {data.regularMarketChangePercent.fmt}</h4>
                        <h4>Market Price :{data.regularMarketPrice.fmt} $</h4>
                      </div>
                      <div>
                        <Modal
                          exchange={data.exchange}
                          exchangeDelay={data.exchangeDataDelayedBy}
                          exchangeMilisec={data.firstTradeDateMilliseconds}
                          marketState={data.marketState}
                          priceHint={data.priceHint}
                          quoteSrcN={data.quoteSourceName}
                          quoteType={data.quoteType}
                          regMarketChF={data.regularMarketChange.fmt}
                          regMarketChR={data.regularMarketChange.raw}
                          regMarketPrevCF={data.regularMarketPreviousClose.fmt}
                          regMarketPrevCR={data.regularMarketPreviousClose.raw}
                          regMarketTimeF={data.regularMarketTime.fmt}
                          regMarketTimeR={data.regularMarketTime.raw}
                          shortName={data.shortName}
                          srcInter={data.sourceInterval}
                          symbol={data.symbol}
                          tradeable={data.tradeable}
                          trigger={data.triggerable}
                          isOpen={isOpen}
                          onClose={(e) => setIsOpen(false)}
                        />
                      </div>
                    </div>
                  </div>
                );
              })}
          </div>
        </>
      ) : (
        <div className="not_logged_page">
          <h1>Welcome to Finan.Stock !</h1>
          <br />
          <h2>Invest Better</h2>
          <LoginButton />
        </div>
      )}
    </>
  );
};

export default StockContent;

你得到这个错误的原因是因为最初 selectFil 是一个空字符串 (const [selectFil, setSelectFil] = useState("")),所以如果你不改变 select 的值,onChange未被触发且 findMatch() 的结果为 undefined。 您可以通过在获取数据后将默认值设置为 selectFil 来解决此问题:

axios
  .request(options)
  .then(function (response) {
    var results = response.data.marketSummaryResponse.result;
    setSelectFil(results[0].exchange); // <--------------------- HERE
    setDatas(results);
    console.log(results);
  })

所以希望你不会再收到错误 TypeError undefined is not a function (near...map) 但这实际上仍然行不通,因为你 datas.find() 没有返回数组;我建议使用 datas.filter() instead,像这样:

const matchData = datas.filter((data) => data.exchange === selected)

但是仍然有一个问题:当 datas 在你的 findMatch 函数(setDatas(matchData))中更新时,它会再次渲染组件和 <select> 选项也将被“过滤”,如下所示:

我要做的是创建一个 filteredDatas 变量 (const [filteredDatas, setFilteredDatas] = useState([])) 并将过滤后的数据存储在其中:

const findMatch = (selected) => {
    const matchData = datas.filter((data) => data.exchange === selected);
    setFilteredDatas(matchData);
};

然后您将通过 filteredDatas 进行映射,它应该可以工作:

{filteredDatas.length > 0 &&
  filteredDatas.map((data, i) => {
    return (
      <div style={{ border: "1px solid gray" }}>
        <h4>Exchange : {data.exchange}</h4>
        <h4>Market : {data.market}</h4>
        <h4>TimeZone : {data.exchangeTimezoneName}</h4>
        <h4>Change Rate : {data.regularMarketChangePercent.fmt}</h4>
        <h4>Market Price :{data.regularMarketPrice.fmt} $</h4>
      </div>
    );
})}

这是完整的沙盒: