readAsArrayBuffer is slow when it try to process a file with more than 300 rows

In my application for processing my file upload, I am using xlxs npm package. And to host the data, I am using readAsArrayBuffer. The performance of readAsArrayBuffer degradding increases when the file’s number of rows increases.

Code block:

readExcelFile(file: File) {
    const reader = new FileReader();
    reader.onload = (e: any) => {
      const data = new Uint8Array(e.target.result);
      const workbook = xls.read(data, { type: 'array' });
      const sheetName = workbook?.SheetNames[0];
      const worksheet = workbook.Sheets[sheetName];
      const jsonData = xls.utils
        .sheet_to_json(worksheet, {
          raw: true,
          defval: null
        })
        .filter((row: any) => {
          return Object.values(row).some(
            (cell) => cell !== null && cell !== undefined && cell !== ''
          );
        });
      const mappedData = this.mapExcelDataToColumns(jsonData);
      this.orders_list =
        mappedData.length > 0 ? mappedData : jsonData ? jsonData : [];
      this.uploadFile(file);
    };
    reader.readAsArrayBuffer(file);
  }

how to fix this issue ? or any better way to handle it ?

Javascript solution [closed]

i have created a card through html and css inside the card i have video and its details(example:duration of the video,, month, video name, etc) it is showing the card via html and css. So my question is, whenever i am adding the second card dynamically through the function in javascript its not showing in the UI. please provide me the solution

i have tried creating a card through html and css inside the card i have video and its details(example:duration of the video, views, 2 months old, video name etc).

expecting
So my question is, whenever i am adding the second card dynamically through the function in javascript its not showing in the UI. please provide me the solution

function cardFormat(title, name, months, duration, thumbnail){
let html=`<div class="card">
<div class="image-class">
      <img
        src="${thumbnail}">
        <div class="capsule">
        
              ${duration}
          
        </div>
    </div>
    <div class="text">
    <h2>"${title}"</h2>
    <span>"${name}" . ${months}ago </span>
  </div>
  </div>`

 document.querySelector(".container").innerHtml = document.querySelector(".container").innerHtml + html;

}
cardFormat("Introduction to Backend | Sigma Web Dev video #2", "CodeWithHarry", 7, "31:22", "https://i.ytimg.com/vi/tVzUXW6siu0/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLACwWOixJVrKLFindK92kYMgTcQbw");
@import url('https://fonts.googleapis.com/css2?family=League+Spartan:[email protected]&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');

*{
    font-family: "Poppins", serif;
}
.card{

    display:flex;
    gap:30px;
}
.image-class img{
    width:250px;
}
.container .text{
    font-size: 14px;
   
}
.image-class{
    position:relative;
}
.duration{
    position: absolute;
    bottom:0;
    right:0;
    background-color: rgba(0, 0, 0,0.7);
    z-index: 10;
    color: #fff;
    padding:4px;
    border-radius: 6px;
    font-size: 13px;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <link rel="stylesheet" href="style.css" />
</head>

<body>
  <div class="container">
    <div class="card">
    <div class="image-class">
      <img
        src="https://i.ytimg.com/vi/tVzUXW6siu0/hqdefault.jpg?sqp=-oaymwEmCKgBEF5IWvKriqkDGQgBFQAAiEIYAdgBAeIBCggYEAIYBjgBQAE=&rs=AOn4CLB6VzxANxt3dHm91HW9lLfDlxvmuA" />
        <div class="capsule">
          <p class="duration">
              31:20
          </p>
        </div>
    </div>
    <div class="text">
    <h2>Installing VS Code &amp; How Websites Work | Sigma Web Development Course - Tutorial #1</h2>
    <span>CodeWithHarry . 1 year ago</span>
  </div>
</div>
  </div>

  <script src="script.js"></script>
</body>

</html>

VSC Plugin button does not download when I click on it

I am trying to make a button in my own VSC plugin which should zip the root directory that I have opened in visual studio code. When I click on the button it doesn’t seem to fire. Trying console.log or vscode.window.showInformationMessage doesn’t show anything either, so I am rather certain the function isn’t correct. I’ve looked up different solutions, but none seem to work. I’ve tried obtaining information from the VSC docs as well, but to no avail.

My package.json (I have removed data which wasn’t relevant for the question):

  "contributes": {
    "commands": [
      {
        "command": "zipView.zipRootFolder",
        "title": "Zip Root Folder"
      }
    ],
    "viewsContainers": {
      "activitybar": [
        {
          "id": "zipView",
          "title": "Zip",
          "icon": "./src/icon/download_button.png"
        }
      ]
    },
    "views": {
      "zipView": [
        {
          "id": "zipButtonView",
          "name": "Zip Button",
          "contextualTitle": "Zip Root Folder",
          "type": "webview"
        }
      ]
    }
  }

My zipButton.ts:

import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import archiver from 'archiver';

export function registerZipButton(context: vscode.ExtensionContext) {
    context.subscriptions.push(
        vscode.window.registerWebviewViewProvider(
            ZipButtonViewProvider.viewType,
            new ZipButtonViewProvider(context.extensionUri)
        )
    );

    context.subscriptions.push(
        vscode.commands.registerCommand('zipView.zipRootFolder', zipRootFolder)
    );
}

class ZipButtonViewProvider implements vscode.WebviewViewProvider {
    public static readonly viewType = 'zipView.zipButtonView';

    constructor(private readonly extensionUri: vscode.Uri) {}

    public resolveWebviewView(
        webviewView: vscode.WebviewView,
        context: vscode.WebviewViewResolveContext,
        _token: vscode.CancellationToken
    ) {
        webviewView.webview.options = {
            enableScripts: true,
        };

        webviewView.webview.html = `
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>Zip Button</title>
                <style>
                    button {
                        background-color: #007acc;
                        color: white;
                        border: none;
                        padding: 10px 15px;
                        border-radius: 4px;
                        cursor: pointer;
                        font-size: 14px;
                    }
                    button:hover {
                        background-color: #005f9e;
                    }
                </style>
            </head>
            <body>
                <button id="zipButton">Zip Root Folder</button>
                <script>
                    const vscode = acquireVsCodeApi();
                    document.getElementById('zipButton').addEventListener('click', () => {
                        vscode.postMessage({ command: 'zip' });
                    });
                </script>
            </body>
            </html>
        `;

        webviewView.webview.onDidReceiveMessage((message) => {
            if (message.command === 'zip') {
                vscode.commands.executeCommand('zipView.zipRootFolder'); // Roep het commando aan
            }
        });
    }
}

// Logic for zip
async function zipRootFolder() {
    vscode.window.showInformationMessage(`Wassup`);
    console.log("wassup");
    const workspaceFolders = vscode.workspace.workspaceFolders;
    if (!workspaceFolders) {
        vscode.window.showErrorMessage('Er is geen workspace geopend.');
        return;
    }

    const rootPath = workspaceFolders[0].uri.fsPath;
    const zipPath = path.join(rootPath, 'root-folder.zip');

    try {
        const output = fs.createWriteStream(zipPath);
        const archive = archiver('zip', { zlib: { level: 9 } });

        output.on('close', () => {
            vscode.window.showInformationMessage(`Map is succesvol gezipt naar: ${zipPath}`);
        });

        archive.on('error', (err) => {
            throw err;
        });

        archive.pipe(output);
        archive.directory(rootPath, false);
        await archive.finalize();
    } catch (error) {
        let errorMessage = 'Fout bij zippen...';
        if (error instanceof Error) {
            errorMessage = error.message;
        }
        vscode.window.showErrorMessage(`Fout bij het zippen: ${errorMessage}`);
    }
}

My extension.ts:

import * as vscode from 'vscode';
import { listExtensions } from './utils/extensionsUtils';
import { monitorDebugSessions } from './utils/debugUtils';
import { onchangeText } from './utils/keydownUtils';
import { registerZipButton } from './components/zipButton';

export function activate(context: vscode.ExtensionContext): void {
    console.log('Your extension is now up and running!');
    

registerZipButton(context);
}

export function deactivate(): void {
    console.log('Your extension is now deactivated!');
    //HERE SHOULD COME THE SELF SIGNED STUFF
}

Get deep nested JSON value

I am trying to get the total_contract_value value from this JSON structure :

{
    "data": [
        {
            "id": 3210,
            "status": "2",
            "date": "2023-11-01 00:00:00.000",
            "value": "123.45",
            "financial_planning": {
                "id": 1234,
                "created_at": "2023-10-20 00:00:00.000",
                "contract": {
                    "id": 12211,
                    "date": "2023-10-20 00:00:00.000",
                    "total_contract_value": "123.45",

I Try using map but the oputput is --> financial_planning will be [object Object] .

const map = new Map(Object.entries(data));
Array.from(map.entries()).forEach(([key, value]) => {
    console.log(key + " is " + Object.entries(value));
    for (let [key2, value2] of Object.entries(value)) {
        console.log("--> "+key2+" will be"+ value2);                                        
    }
});

How can i get the total_contract_value ?

Wich would be the simplest way ?

Also i am inside an old reactjs application but i am new to reactjs, this is why i am trying using javascript.

Page scrolling with inertia and elasticity

Apologies if this is not the right forum for this question, but I don’t really know where else to ask it!

I am creating a HTML/CSS/JS mobile and tablet app mock-up. Because I want to give my client a feel for the UX of the app even when they view on desktop, I’ve hidden the scrollbars and created a small JavaScript “draggable” library, which allows the user to scroll a page or container by touching and dragging (or mousedown-ing and mousemove-ing on desktop) just like on a touch device. With this library I can easily create scroll inertia and even an elastic “bounce back” when an element is scrolled beyond its extents:

enter image description here

If I get a pointerup event and the cursor has moved less than some arbitrary number of pixels, I assume the user “clicked” something, otherwise I scroll the element if it is what I’ve deemed “draggable”.

It all works okay, but I have a few issues now, a few days later:

  1. I’m having to assign a tapEvent property to any child elements that I want to be clickable, since I’m intercepting the pointerDown event of the parent and can’t simply have a click event listener for those elements, which is becoming cumbersome
  2. Sometimes, my dragging simply doesn’t work – I see a ghosted version of the element instead, like when I drag an image on a web page
  3. I’ve now decided to have scrollbars after all – probably using perfect-scrollbar, which I’ve been a fan of for years.
  4. I’d like to allow scrolling with a mousewheel too.

So my question is – is there an existing, off-the-shelf JS library that will already do what I’m attempting? Have I attempted to (badly!) reinvent the wheel!?

Thanks so much for any pointers!

Open link via jQuery identified by class

I have hundreds of rows of links. I do not want links to have their URL addresses hardcoded into the pages via href when loaded in, rather keep it to a function and their destination confirmed by their ID, triggered by their class.

Link looks like:

<a id="111112" class="openCertLink" href="#">Line 1 - <b>Line 2</b>. ID: "111112"</a>

I’ve tried using the .click jQuery function like it works for everything else, yet here for links it’s just a dud, doing nothing. All other suggestions online are outdated with security issues that aren’t even allowed on browsers anymore, use ID’s not classes or just 30 year old hardtyped href.

function:

$(".openCertLink").click(function(event){
  alert("Link away");
  // ...and so on
});

I feel like something simple has stumbled me. ID’s work and so on but why today do the classes not want to get triggered by jQuery.

Thanks.

Why are sortField and sortOrder undefined in the API URL despite being passed in the refetch function?

I’m building a React component with a sortable ANTD table, and I’m using a refetch function to fetch jobs data. The refetch function accepts parameters for pagination and sorting, including sortField and sortOrder. However, when clicking the table header to sort, the sortField and sortOrder variables are logged as undefined, and the API URL doesn’t include the sorting parameters.

const refetch = (
    fromIndex: number,
    maxCount: number,
    append: boolean = true,
    sortField?: string,
    sortOrder?: string
) => {
    let url = `/tasks/list?start=${fromIndex}&count=${maxCount}`;
    if (sortField && sortOrder) {
        url += `&sortField=${sortField}&sortOrder=${sortOrder}`;
    }

    console.log("API URL:", url);
    console.log("Sort Field Sent:", sortField);
    console.log("Sort Order Sent:", sortOrder);

};

Table columns:

const JobTableColumns: (
    refetch: (fromIndex: number, maxCount: number, append: boolean, sortField?: string, sortOrder?: string) => void
) => DTableTypes.ColumnsData<Task> = (refetch) => [
    {
        key: 'job_name',
        title: 'Job Name',
        dataIndex: ['details', 'job_name'],
        sorter: true,
        sortDirections: ['ascend', 'descend'],
        onHeaderCell: () => ({
            onClick: () => {
                const sortOrder = 'asc';
                console.log("Sorting column job_name:", { field: 'job_name', order: sortOrder });
                refetch(0, JOBS_TABLE_PAGE_LENGTH, false, 'job_name', sortOrder);
            },
        }),
    },
];

JobsContainer

const JobsContainer: React.FunctionComponent = () => {
    const { jobs, loading, refetch } = jobsService.useGetJobs();

    const refetchTable = () => {
        refetch(0, JOBS_TABLE_PAGE_LENGTH, false); // Reload the table
    };

    const jobsCount = jobs?.jobs?.length || 0;

    const onMore = () => {
        refetch(jobsCount, JOBS_TABLE_PAGE_LENGTH, true); // Load more
    };

    useEffect(() => {
        refetch(0, JOBS_TABLE_PAGE_LENGTH, false); // Initial load
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    return (
        <JobsView
            loading={loading}
            counters={{ items: jobsCount, total: jobs?.total || 0 }}
            jobs={jobs?.jobs || []}
            refetch={refetchTable}
            onMore={onMore}
        />
    );
};

export default JobsContainer;

JobTable

return (
    <>
        <div className="JobsTable" id="jobsTable">
            <DTable
                columns={JobTableColumns(refetch)} // Pass the refetch function directly
                dataCy="JOBS_TABLE"
                dataSource={jobs}
                emptyState={{
                    text: "There are 0 jobs available.",
                }}
                getRowKey={(record): string => record.job_id}
                loading={isLoading}
                rowActions={{
                    renderer: renderRowActions,
                }}
                renderFooter={renderFooter}
            />
        </div>
    </>
);

JobView

const JobsView: React.FunctionComponent<JobsViewProps> = ({ loading, counters, jobs, refetch, onMore }) => {
    const permissionObject = usePermission(jobsPermissions);

    return (
        <MainSectionLayout hasFilterPanel={false}>
            <JobsSectionHeader slot="SectionHeader" />
            <JobsTopSection slot="FilterSelectedToolbar" counters={counters} permissions={permissionObject} />
            <JobsTable
                slot="Table"
                isLoading={loading}
                jobs={jobs}
                refetch={refetch}
                totalJobs={counters.total}
                onMore={onMore}
            />
        </MainSectionLayout>
    );
};

export default JobsView;

Even though I’m explicitly passing sortField and sortOrder to refetch, they show up as undefined in the logs.

What could be causing this issue? Am I missing something in how React handles the function call or parameter binding?

Themeco WordPress theme (add a JS call #scs-ols-widget=sites/[siteID]/details to a button)

I am using a customer theme (Themeco) on the wordpress site and the button looks like this via the inspector:

Hi,

New to Stackoverflow and hoping someone could help me resolve this issue. I am not a developer by trade, but have worked with WordPress on and off.

I am using a third party booking theme which rans of a JS script

To call the script the documentation said to use this:

<a href=”#scs-ols-widget=sites/[siteid]/details“>Book now</a>

I am using a customer theme (Themeco) on the wordpress site and the button looks like this via the inspector:
<div class="x-column x-sm x-1-3 e2-e5 m2-9 m2-a">
    <a class="x-anchor x-anchor-button has-graphic e2-e6 m2-1p" tabindex="0" id="book-now" href="#scs-ols-widget=sites/[storeID]/details">
        <div class="x-anchor-content">
            <span class="x-graphic" aria-hidden="true">
                <i class="x-icon x-graphic-child x-graphic-icon x-graphic-primary" aria-hidden="true" data-x-icon-s=""></i>
                <i class="x-icon x-graphic-child x-graphic-icon x-graphic-secondary" aria-hidden="true" data-x-icon-s=""></i>
            </span>
            <div class="x-anchor-text">
                <span class="x-anchor-text-primary" data-x-single-anim="x-slide-top">Book now</span>    
            </div>
        </div>
    </a>
</div>

When i add the configuration of setting the URL #scs-ols-widget=sites/[storeID]/details

The “-” char is making the book now button dissappear.

I know the URL “#scs-ols-widget=sites/[storeID]/details” works, as i have implemented in the WordPress menu option via a customer link setup.

If anyone could help me with this that would be much appreciate it.

Thank you all in advanced

Using ChatGPT, i tried a couple of things:

Method 1:
replacing – with the char code, that did not work, it resulted in the #scs-ols-widget=sites/[StoreID]/details appended to the website’s url: website.com.au/#scs-ols-widget=sites/[storeid]/details

Any help will be much appreciated,

thank you

Your application tried to access @babel/preset-env, but it isn’t declared in your dependencies; this makes the require call ambiguous and unsound

Recently I started updating the dependencies of my react application (that hasn’t been touched in several years). I also upgraded from yarn 4.1.0 to 4.6.0. I also added nodeLinker: pnp to my .yarnrc.yml file. Now i get this error when starting the application with “yarn start”:

srcuseMyHook.ts
  Line 0:  Parsing error: Your application tried to access @babel/preset-env, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound.        

Required package: @babel/preset-env (via "@babelpreset-env")
Required by: appui

Require stack:
- appui.yarncache@babel-core-npm-7.19.0-50eaedd5da-60a01c89e8.zipnode_modules@babelcorelibconfigfilesindex.js
- appui.yarncache@babel-core-npm-7.19.0-50eaedd5da-60a01c89e8.zipnode_modules@babelcorelibconfigfilesplugins.js
- appui.yarncache@babel-core-npm-7.19.0-50eaedd5da-60a01c89e8.zipnode_modules@babelcorelibindex.js
- appui.yarn__virtual__@rollup-plugin-babel-virtual-48b162daeacache@rollup-plugin-babel-npm-5.3.1-6039a4d033-eb3ee5fedd.zipnode_modules@rollupplugin-babeldistindex.js
- appui.yarncacheworkbox-build-npm-6.5.4-71d02fae43-147373efa3.zipnode_modulesworkbox-buildbuildlibbundle.js
- appui.yarn__virtual__workbox-webpack-plugin-virtual-83d0dca87dcacheworkbox-webpack-plugin-npm-6.5.4-3842d0960f-12e2990df0.zipnode_modulesworkbox-webpack-pluginbuildgenerate-sw.js
- appui.yarn__virtual__workbox-webpack-plugin-virtual-83d0dca87dcacheworkbox-webpack-plugin-npm-6.5.4-3842d0960f-12e2990df0.zipnode_modulesworkbox-webpack-pluginbuildindex.js
- appui.yarn__virtual__react-scripts-virtual-2cc3c53625cachereact-scripts-npm-5.0.1-d06bd2d5ad-1727f9b460.zipnode_modulesreact-scriptsconfigwebpack.config.js
- appui.yarn__virtual__react-scripts-virtual-2cc3c53625cachereact-scripts-npm-5.0.1-d06bd2d5ad-1727f9b460.zipnode_modulesreact-scriptsscriptsstart.js

The weird thing is, if I change to nodeLinker: node-modules, no error is shown. There must be some incompatibility with yarn pnp (I got the idea to switch from this post).

I would like to know why this error appears, as I would like to use nodeLinker: pnp instead. It seems to be related to react-scripts?

Converting CSS hover event to javascript Click event

The CSS hover code works great for PC users, but I discovered that mobile users can’t really use hover on links, so I am hoping to convert this CSS code to JavaScript or jQuery so that it works using the click event.

.pages-links-sub div.dropdown-contentc {
  display:none;
}
.columnb-sub > .pages-links-sub {
  display:none;
}
.columnb-sub:hover > .pages-links-sub {
  display:block;
  div.dropdown-contentc {
    display:block;
  }
}

It is part of a multi-sub dropdown menu. I tried using toggle, but I had issues when there were other sub dropdowns.
This is a chunk of the HTML of the dropdown menu.

<div class="columnb">
  <p class="pages-toptext">Standard Settings</p>
  <div class="pages-links">
    <a href="#">Link 1</a>

      <div class="columnb-sub">
        <a href="#">SubLinks 1 <i class="fa fa-caret-down"></i></a>
        <div class="pages-links-sub">
          <div class="dropdown-contentc">
            <div class="columnb">
              <a href="#">SubLink 1</a>
              <a href="#">SubLink 2</a>
              <a href="#">SubLink 3</a>
            </div>
          </div>
        </div>
      </div>
      <div class="columnb-sub">
        <a href="#">SubLinks 2 <i class="fa fa-caret-down"></i></a>
        <div class="pages-links-sub">
          <div class="dropdown-contentc">
            <div class="columnb">
              <a href="#">SubLink 1</a>
              <a href="#">SubLink 2</a>
              <a href="#">SubLink 3</a>
            </div>
          </div>
        </div>
      </div>
      
    <a href="#">Link 2</a>
    <a href="#">Link 3</a>
  </div>
</div>

When one sub dropdown opens, all other dropdowns should close.

Changing the width of one column changes the width of the other columns with colResize.js

I’m using colResize to adjust the width of the columns, but when I reduce the the width of one column, the width of the others columns change too. I think it is because the table has a fixed width and when one column is reduced, the others get bigger to take up the table width.

let table = new DataTable("#myTable", {
    pageLength: 25,
    info: false,
    colResize: {
      mode: "overflow",
      realtime: true,
    },
    responsive: true,
    scrollX: true,
    autoWidth: false,
    lengthChange: false,
    searching: true,
    fixedHeader: true,
    destroy: true,
    processing: true,
    stateSave: true,
    scrollCollapse: true,
  });

  let rowsData = [
    ["Jane Smith", "Manager", "London", "45", "2017/05/12", "$90,000"],
    ["Mark Wilson", "Designer", "Berlin", "78", "2021/08/11", "$23,000"],
    ["Mark Wilson", "Designer", "Berlin", "56", "2021/08/11", "$90,000"],
    ["Jane Smith", "Manager", "London", "45", "2019/03/29", "$23,000"],
    ["Oscar Gutierrez", "Programmer", "Tokio", "19", "2019/03/29", "$23,000"],
    ["Diego", "Programmer", "Paris", "22", "2019/03/29", "$132,000"],
    ["Jordi", "Programmer", "Paris", "32", "2019/03/29", "$132,000"],
  ];

  table.rows.add(rowsData).draw();

  return table;

I need the table to work like an Excel, if you are changing the size of a column only the column on the left changes, the others continue with the same width. And if you make a column smaller, the table will be smaller too.

I’m using the version 1.13.1 of datatables and the latest version of the plugin jquery.dataTables.colResize.js.

Error: This object has been frozen and should not be mutated

i have this map object with key value pair as shown below.

let input = new Map([
    [
        "3984-a731-bc8751ca9695",
        {
            "groupId": "dfd622ae-c684-3984",
            "testError": "java.lang.NullPointerExceptionn",
        }
    ],
    [
        "3235-9751-f3d8fe441b69",
        {
            "groupId": "3dd29f05-f17a-3235",
            "testError": "java.lang.NullPointerExceptionn",
        }
    ],
])

When i do this delete function below, it gives a run time error stating that Error: [Immer] This object has been frozen and should not be mutated

input?.delete('3235-9751-f3d8fe441b69');

Earlier i had this input saved in redux and i read somewhere that map object in redux gives this issue. so i used the reacts useState functionality and saved the input in a component and passed it to child components wherever needed. the error still remains.

Can someone please shed some light on this.

How to handle login errors and display them in a modal window without redirecting?

everybody. I have a modal window and a method for Login, i.e. there is no separate view for the Login page.

I am facing a problem, when the login data is not correct, it displays an error directly in the modal window without redirecting.

I solved this problem by using

return Json

but then I found out that this is not a good option and a redirect should be used.

But where should I use redirect if there is no login page?

It was possible to redirect to the same page, force with js to open a modal window and display an error message, but this is a bad option.

It’s working now.

[HttpPost("login")]
    public IActionResult Login([FromForm] User user)
    {
        if (user.Login is not _login || user.Password is not _password)
            return Json(new { success = false, message = "Invalid login or password" });

        var claims = new List<Claim> { new(ClaimTypes.Name, user.Login) };
        var claimsIdentity = new ClaimsIdentity(claims, "CookieAuth");
        var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);

        HttpContext.SignInAsync("CookieAuth", claimsPrincipal).Wait();

        return Json(new { success = true, redirectUrl = "/" });
    }
<div class="modal fade login" id="loginModal" tabindex="-1" aria-labelledby="loginModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-body">
                <div class="login-form">
                    <div class="text-center">
                        <h1>Disk</h1>
                    </div>
                    <div id="loginError" class="alert alert-danger text-center" style="display: none;"></div>
                    <form id="loginForm">
                        <div class="form-group mb-3">
                            <input type="text" name="login" class="form-control" id="login" placeholder="Enter login">
                        </div>
                        <div class="form-group mb-3">
                            <input type="password" name="password" id="password" class="form-control" placeholder="Enter Password">
                        </div>
                        <div class="text-center">
                            <button type="submit" class="btn btn-primary w-100 welcome login-button">Login</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>

js

$(document).ready(function() {
    $('#loginModal').on('shown.bs.modal', function () {
        $('#loginError').hide();
    });

    $("#loginForm").on("submit", function(e) {
        e.preventDefault();
        var form = $(this);
        $.ajax({
            url: '/login',
            type: 'POST',
            data: form.serialize(),
            success: function(response) {
                if(response.success) {
                    window.location.href = response.redirectUrl;
                } else {
                    $('#loginError').show().text(response.message);
                }
            },
            error: function() {
                $('#loginError').show().text('There was an error, try again.');
            }
        });
    });

I’m trying to display an error message in a modal window

Proxying External API Requests in Next.js 15

I’m working on a Next.js 15 app that integrates with an external API (on a separate backend server), and I’m facing issues with integrating it correctly.

Here’s the setup:

I created a custom fetcher, essentially an Axios instance that handles:

  1. Retrieving JWT from cookies
  2. Attaching the token to a request header for backend authentication
  3. Handling token refresh

However, this setup only works with server components since I can’t access cookies on the client side. I thought of creating a separate fetcher for the client, but synchronizing sessions and tokens across both fetchers and duplicating the token-refreshing logic feels cumbersome.

The only other option I considered was using Next.js API routes or server actions:

  • Server actions are helpful for mutations, but due to sequential execution, they don’t seem ideal for GET requests.
  • API routes would require duplicating backend endpoints and handling query parameters and responses, which seems inefficient.

So, I decided to try proxying requests through Next.js API routes. I created a catch-all route /api/external/[[...proxy]] with the following code to forward requests to the external API (serverFetcher requests):

import { NextRequest, NextResponse } from 'next/server';
import { serverFetcher } from '@libs/server-fetcher';

async function handler(request: NextRequest) {
  const headers: Record<string, string> = {};

  request.headers.forEach((value, key) => {
    headers[key] = value;
  });

  const response = await serverFetcher.request({
    url: request.url.replace(request.nextUrl.origin + '/api/external', ''),
    method: request.method,
    data: request.body,
    headers,
  });
  
  const responseHeaders: Record<string, string> = {};
  Object.entries(response.headers).forEach(([key, value]) => {
    responseHeaders[key] = value;
  });

  return NextResponse.json(response.data, {
    status: response.status,
    statusText: response.statusText,
    headers: responseHeaders,
  });
}

export const dynamic = 'force-dynamic';

export {
  handler as GET,
  handler as POST,
  handler as DELETE,
  handler as PATCH,
  handler as PUT
};

And this is how I planned to use it:

export const clientFetcher: HttpClient = axios.create({
  baseURL: '/api/external'
});

const srProductsService = new ProductsService(serverFetcher); // <-- Server Fetcher passed to a generic service
const clProductsService = new ProductsService(clientFetcher); // <-- Client Fetcher passed to the same service, which reduces code duplications and saves typing

export { srProductsService, clProductsService };

Since this is executed on the server, I can safely use the serverFetcher here and avoid duplicating backend endpoints. However, I’m receiving a 304 Not Modified status code, and I’m not sure why:

Error:

Error [AxiosError]: Request failed with status code 304
> 17 |   const response = await serverFetcher.request({
     |                   ^ 
  18 |     url: request.url.replace(request.nextUrl.origin + '/api/external', ''),

Questions:

  1. Can anyone help me troubleshoot this issue with the 304 response?
  2. What is your approach to integrating Next.js with external third-party APIs while handling JWTs and sessions efficiently?
  3. Do you have any recommendations for improving this proxying setup, and do you see any potential drawbacks of this approach?

Any advice or insights would be appreciated!