gadicc / node-yahoo-finance2

Unofficial API for Yahoo Finance
https://www.npmjs.com/package/yahoo-finance2
MIT License
353 stars 58 forks source link

URLSearchParams is not a constructor - Next.js, React #771

Open spyderdsn opened 1 month ago

spyderdsn commented 1 month ago

Bug Report

Describe the bug

Unable to call the API in Next.js, Unhandled Runtime Error Error: Failed to fetch dividend data: URLSearchParams is not a constructor

Minimal Reproduction

"use client";

import { useEffect, useState } from "react";
import yahooFinance from "yahoo-finance2";

export default function Home() {
  const [apiData, setApiData] = useState(null);

  async function getDividends(symbol, startDate, endDate) {
    try {
      const dividends = await yahooFinance.historical(symbol, {
        period1: startDate,
        period2: endDate,
        events: "dividends", // Adjusted the event type to 'dividends'
        interval: "1mo", // Monthly interval
      });

      setApiData(dividends);
    } catch (error) {
      throw new Error(`Failed to fetch dividend data: ${error.message}`);
    }
  }

  useEffect(() => {
    getDividends("QQQ", "2023-01-01", "2023-12-31");
  }, []);

  return (
    <main>
      <h1>{apiData ? apiData.dividends : "Loading..."}</h1>
    </main>
  );
}

CodeSandbox url: https://codesandbox.io/p/devbox/pedantic-herschel-s39y95?embed=1&file=%2Fapp%2Fpage.tsx

Environment

  "dependencies": {
    "next": "14.2.1",
    "react": "^18",
    "react-dom": "^18",
    "yahoo-finance2": "2.11.2"
  },
gadicc commented 1 month ago

Hey, I need to look into this further, and figure out what's going wrong where, as obviously URLSearchParams does exist in the browser and we do have a browser environment that accommodates this which is what should be imported according to the package.json rules. (My suspicion is it's a Next app router edge case, but I haven't looked yet).

In the meantime however, wanted to make sure you saw the warning about running yf2 in the browser in the README. For example, your code above won't work as it will be blocked by a CORS request. Also - not mentioned in the README yet - but more and more parts of yahoo finance are going behind a cookie-and-crumb wall, which currently will just break altogether in the browser. We may well remove browser support completely in the future.

Anyway, I'll get back to you on this issue when I have a chance but I strongly, strongly, strongly recommend to not try do this on the browser side. Rather have the client access an API route which does the actual yf2 invocation. If it's not clear how to do this, I'll try setup an example on codesandbox (P.S. unfortunately your shortened link did actually route through to csb `:).

spyderdsn commented 1 month ago

Hey, I need to look into this further, and figure out what's going wrong where, as obviously URLSearchParams does exist in the browser and we do have a browser environment that accommodates this which is what should be imported according to the package.json rules. (My suspicion is it's a Next app router edge case, but I haven't looked yet).

In the meantime however, wanted to make sure you saw the warning about running yf2 in the browser in the README. For example, your code above won't work as it will be blocked by a CORS request. Also - not mentioned in the README yet - but more and more parts of yahoo finance are going behind a cookie-and-crumb wall, which currently will just break altogether in the browser. We may well remove browser support completely in the future.

Anyway, I'll get back to you on this issue when I have a chance but I strongly, strongly, strongly recommend to not try do this on the browser side. Rather have the client access an API route which does the actual yf2 invocation. If it's not clear how to do this, I'll try setup an example on codesandbox (P.S. unfortunately your shortened link did actually route through to csb `:).

Hi @gadicc , I fixed the URL, and also did another example in Node.js which works. So you will suggest making a Node API and not to use SSR language? Thanks for your quick reply!

Node CodeSandbox: https://codesandbox.io/p/devbox/festive-dewdney-7ysrcn

spyderdsn commented 1 month ago

Ok, Next.js do not like this:

Screenshot 2024-05-02 at 6 09 13 PM
gadicc commented 1 month ago

I fixed the URL, and also did another example in Node.js which works. So you will suggest making a Node API and not to use SSR language? Thanks for your quick reply!

Ah amazing, great job! And my pleasure.

Yeah, Node is best. But, RSCs should work fine, even though I never tried. If you're using Next's app router, should be enough to drop the "use client", and then instead of useState and useEffect, you could const apiData = React.use(getDividends(...)).

But yeah, if you're already using the Node API and everything is working, up to you. I haven't actually ever tried the RSC way.