【问题标题】:TypeError undefined is not a function (near...map)TypeError undefined is not a function (near...map)
【发布时间】:2022-01-17 15:01:46
【问题描述】:

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

整个网站崩溃。 请帮忙!

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;

【问题讨论】:

    标签: reactjs filter mapping rendering


    【解决方案1】:

    您收到此错误的原因是因为最初 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)) 中更新时,它会再次渲染组件并且&lt;select&gt; 选项也将被“过滤”,如你所见下面:

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

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

    然后您将映射到过滤数据,它应该可以工作:

    {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>
        );
    })}
    

    这里是完整的沙盒:

    【讨论】:

      猜你喜欢
      • 2020-02-15
      • 2019-10-14
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-26
      • 2015-06-24
      相关资源
      最近更新 更多