Why jest.useFakeTimers() is not working for a setTimeout inside a Promise inside a HTTP Request?

I have a test usinging jest thats try to validate an result of a http request to an endpoint (nextjs) which results in a timeout depending on the input parameters like: “/timeout/300”

this is the test
https://github.com/Streeterxs/timeout-server/blob/main/src/app/api/timeout/%5Bms%5D/__tests__/%5Bms%5D.spec.ts#L18

// why this is not working?
it.skip("Should successfully timeout for 300ms", async () => {

  const ms = '300';
  const params: Record<string, string | string[]> = {ms};

  const testApiHandlerPromise = testApiHandler({
    appHandler: timeoutRouteHandler,
    params,
    test: async ({ fetch }) => {

      const responsePromise = fetch({ method: "GET" });

      // https://stackoverflow.com/questions/51126786/jest-fake-timers-with-promises
      jest.runAllTimers();
      const response = await responsePromise;

      const json = await response?.json();

      console.log({json})
      expect(response.status).toBe(200);
      expect(json).toStrictEqual({
        error: null,
        success: `Timeouted ${ms}ms`
      });
      expect(setTimeout).toHaveBeenCalledTimes(1);
    },
  });

  // https://stackoverflow.com/questions/51126786/jest-fake-timers-with-promises
  // dont know if this is needed, but since this promise runs inside the package scope I tried it out
  // probably occurs because of the callback code of test function
  // but I tried to modify the code and it stuck right on the setTimeout function
  jest.runAllTimers();

  await testApiHandlerPromise;
});

yes, Im using a package that encapsulates the test Im trying todo. It justs executes the global fetch function in a way that nextJs understands it (at least it was what I undestood)

Already tried the differents solutions that deals with setTimeout + promises out there but none worked (I think it is because the promise is encapsulated in a http request dont know for sure but it would be cool if anyone answers that too)

¿Qué lenguaje me recomendarían para un programa o pagina que sea local para un contador de archivos de excel de cotizaciones? [closed]

Estoy empezando en esto de la programación pero me piden que haga un programa para llevar mejor el control de archivos de cotizaciones que son en excel quiero hacer un programa para computadora donde se suba el archivo en excel y se guarde en la misma en un bd que lleve nombre, id y fecha para poder filtrar y poder buscar de mejor manera y no permitir que se repitan las cotizaciones de nuevo. Pero quiero saber que me recomiendan para una mejor ejecución.

espero me puedan ayudar y dar su mejor consejo. estaba pensando usar electron.js pero no tengo experiencia en el

How can I adjust the hover effect to show price and indicator info directly on the stock chart when using Vite.js?

I referred to this example on CodePen using react-financial-charts library, specifically attached here: https://codesandbox.io/p/sandbox/react-financial-charts-demo-forked-zw4o4?file=%2Findex.js. However, when I re-coded it using Vite.js and ran the file, the chart mostly displayed like the CodePen demo, except for the hover effect as shown in the example. Where did I go wrong?
My code here
App.jsx

import React from "react";
import ReactDOM from "react-dom";
import { format } from "d3-format";
import { timeFormat } from "d3-time-format";
import {
  elderRay,
  ema,
  discontinuousTimeScaleProviderBuilder,
  Chart,
  ChartCanvas,
  CurrentCoordinate,
  BarSeries,
  CandlestickSeries,
  ElderRaySeries,
  LineSeries,
  MovingAverageTooltip,
  OHLCTooltip,
  SingleValueTooltip,
  lastVisibleItemBasedZoomAnchor,
  XAxis,
  YAxis,
  CrossHairCursor,
  EdgeIndicator,
  MouseCoordinateX,
  MouseCoordinateY,
  ZoomButtons,
  withDeviceRatio,
  withSize
} from "react-financial-charts";
import { initialData } from "./data.jsx";
// import ChartExample from "./Chart.jsx";

const rotateArray2 = function (nums, k) {
  // reverse helper function
  function reverse(arr, start, end) {
    while (start < end) {
      [arr[start], arr[end]] = [arr[end], arr[start]];
      start++;
      end--;
    }
  }

  k %= nums.length;

  reverse(nums, 0, nums.length - 1);
  reverse(nums, 0, k - 1);
  reverse(nums, k, nums.length - 1);

  return nums;
};

const App = () => {
  const ScaleProvider = discontinuousTimeScaleProviderBuilder().inputDateAccessor(
    (d) => new Date(d.date)
  );
  const height = 700;
  const width = 900;
  const margin = { left: 0, right: 48, top: 0, bottom: 24 };

  const ema12 = ema()
    .id(1)
    .options({ windowSize: 12 })
    .merge((d, c) => {
      d.ema12 = c;
    })
    .accessor((d) => d.ema12);

  const ema26 = ema()
    .id(2)
    .options({ windowSize: 26 })
    .merge((d, c) => {
      d.ema26 = c;
    })
    .accessor((d) => d.ema26);

  const elder = elderRay();

  const rotateArray2 = function (nums, k) {
    // reverse helper function
    function reverse(arr, start, end) {
      while (start < end) {
        [arr[start], arr[end]] = [arr[end], arr[start]];
        start++;
        end--;
      }
    }

    k %= nums.length;

    reverse(nums, 0, nums.length - 1);
    reverse(nums, 0, k - 1);
    reverse(nums, k, nums.length - 1);

    return nums;
  };

  const calculatedData = elder(ema26(ema12(rotateArray2(initialData))));
  const { data, xScale, xAccessor, displayXAccessor } = ScaleProvider(
    rotateArray2(initialData)
  );
  const pricesDisplayFormat = format(".2f");
  const max = xAccessor(data[data.length - 1]);
  const min = xAccessor(data[Math.max(0, 0)]);
  const xExtents = [min, max + 5];

  const gridHeight = height - margin.top - margin.bottom;

  const elderRayHeight = 100;
  const elderRayOrigin = (_, h) => [0, h - elderRayHeight];
  const barChartHeight = gridHeight / 4;
  const barChartOrigin = (_, h) => [0, h - barChartHeight - elderRayHeight];
  const chartHeight = gridHeight - elderRayHeight;
  const yExtents = (data) => {
    return [data.high, data.low];
  };
  const dateTimeFormat = "%d %b";
  const timeDisplayFormat = timeFormat(dateTimeFormat);

  const barChartExtents = (data) => {
    return data.volume;
  };

  const candleChartExtents = (data) => {
    return [data.high, data.low];
  };

  const yEdgeIndicator = (data) => {
    return data.close;
  };

  const volumeColor = (data) => {
    return data.close > data.open
      ? "rgba(38, 166, 154, 0.3)"
      : "rgba(239, 83, 80, 0.3)";
  };

  const volumeSeries = (data) => {
    return data.volume;
  };

  const openCloseColor = (data) => {
    return data.close > data.open ? "#26a69a" : "#ef5350";
  };



  return (
    <ChartCanvas
      height={height}
      ratio={3}
      width={width}
      margin={margin}
      data={data}
      displayXAccessor={displayXAccessor}
      seriesName="Data"
      xScale={xScale}
      xAccessor={xAccessor}
      xExtents={xExtents}
      zoomAnchor={lastVisibleItemBasedZoomAnchor}
    >
      <Chart
        id={2}
        height={barChartHeight}
        origin={barChartOrigin}
        yExtents={barChartExtents}
      >
        <BarSeries fillStyle={volumeColor} yAccessor={volumeSeries} />
      </Chart>
      <Chart id={3} height={chartHeight} yExtents={candleChartExtents}>
        <XAxis showGridLines showTickLabel={false} />
        <YAxis showGridLines tickFormat={pricesDisplayFormat} />
        <CandlestickSeries />
        <LineSeries yAccessor={ema26.accessor()} strokeStyle={ema26.stroke()} />
        <CurrentCoordinate
          yAccessor={ema26.accessor()}
          fillStyle={ema26.stroke()}
        />
        <LineSeries yAccessor={ema12.accessor()} strokeStyle={ema12.stroke()} />
        <CurrentCoordinate
          yAccessor={ema12.accessor()}
          fillStyle={ema12.stroke()}
        />
        <MouseCoordinateY
          rectWidth={margin.right}
          displayFormat={pricesDisplayFormat}
        />
        <EdgeIndicator
          itemType="last"
          rectWidth={margin.right}
          fill={openCloseColor}
          lineStroke={openCloseColor}
          displayFormat={pricesDisplayFormat}
          yAccessor={yEdgeIndicator}
        />
        <MovingAverageTooltip
          origin={[8, 24]}
          options={[
            {
              yAccessor: ema26.accessor(),
              type: "EMA",
              stroke: ema26.stroke(),
              windowSize: ema26.options().windowSize
            },
            {
              yAccessor: ema12.accessor(),
              type: "EMA",
              stroke: ema12.stroke(),
              windowSize: ema12.options().windowSize
            }
          ]}
        />

        <ZoomButtons />
        <OHLCTooltip origin={[8, 16]} />
      </Chart>
      <Chart
        id={4}
        height={elderRayHeight}
        yExtents={[0, elder.accessor()]}
        origin={elderRayOrigin}
        padding={{ top: 8, bottom: 8 }}
      >
        <XAxis showGridLines gridLinesStrokeStyle="#e0e3eb" />
        <YAxis ticks={4} tickFormat={pricesDisplayFormat} />

        <MouseCoordinateX displayFormat={timeDisplayFormat} />
        <MouseCoordinateY
          rectWidth={margin.right}
          displayFormat={pricesDisplayFormat}
        />

        <ElderRaySeries yAccessor={elder.accessor()} />

        <SingleValueTooltip
          yAccessor={elder.accessor()}
          yLabel="Elder Ray"
          yDisplayFormat={(d) =>
            `${pricesDisplayFormat(d.bullPower)}, ${pricesDisplayFormat(
              d.bearPower
            )}`
          }
          origin={[8, 16]}
        />
      </Chart>
      <CrossHairCursor />
    </ChartCanvas>
  );
};

export default App;

main.jsx

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import './index.css'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

data.jsx I follow by example in codepen I show before

I want to debug and fix the chart more friendly and beautifully

upload file from browser using https for progress update

Axios seems to work quite fine for file uploads, but, since it’s a Front end applications, I wanted to avoid using a third party lib for a simple file upload task.

My requirements are to be able to upload a file and get update on progress, file potentially 1-3GB in size.

Note, I can’t use FormData because, I eventually want to use S3 presigned urls which use PUT and expect raw binary.

Other than using axios, I came across 2 options:

  1. Fetch
  2. Https module

While uploading with fetch seems to be simple, there doesn’t seem to be a way to get progress update.

And the hurdle I came with https is that it seems to need a Readstream, and in browser I can’t use the fs module. So, just seeing the interfaces, I did a hacky bit of code like this(taking a similar example, but, this one uses form data):

import https from 'https';

// file = event.target.files[0]

export async function uploadFile(
  url: string,
  file: File,
  onProgress: () => void = noOp,
  method = REQ.PUT,
) {
  
 let progressDataLength = 0;
  let data = "";
  
  return new Promise((resolve, reject) => {
    const req = https.request(
      {
        hostname: url,
        method: method,
        headers: {
          "Content-Type": file.type,
          "Content-Length": file.size,
        },
      },
      function (res) {
        res.on("data", (chunk) => {
          progressDataLength += chunk.size;
          data += chunk;
          onProgress();
          console.log("Total received: ", `${chunk.size}/${file.size}`);
        });
        res.on("end", () => {
          resolve("Mydata: " + data);
        });
      },
    );  
       
     // MY HACKY CODE BIT
     const startConversionTime = new Date().getTime();
     Readable.from(Buffer.from(await file.arrayBuffer())).pipe(req);
     console.log(
       "Total conversion time taken: ",
       new Date().getTime() - startConversionTime,
    );  

    req.end();
  });
}

While this particular code produced the error below, I’m not sure if this is even legit at all? ( Is the conversion done right? and, I can’t really find examples of File being converted to readable stream )

TypeError: The “listener” argument must be of type Function. Received type object

What are my options of implementing this function and how can it be done?

Locomotive Smooth Scroll Lagging Over Image-Heavy Infinite Scroller

Context:
I’m working on a college project where I’ve implemented smooth scrolling using Locomotive Scroll. The page has an infinite side-scrolling section that displays a lot of images and logos.

Problem:
When the smooth scroll reaches the image-heavy section, the entire page starts to lag. The infinite side scroller works fine on its own, but combined with Locomotive Scroll, the performance drops significantly, takes a while but work oki later the first time is laggy.

What can I do to prevent Locomotive Scroll from lagging when it encounters the image-heavy infinite side-scroller?

idk if i should just paste my html , css and js as they scroller info mighth be imp so i will just link my github repo where i have been uploding it
https://github.com/shindeparth/Brainery

sry its my first time so idk the correct way

idk much actully im a design studen to have intrest in codding soo im figuring it out myself. but it works fine with locomotive off ,

Play video with audio automatically like youtube [duplicate]

I’ve done extensive research, and what I’ve found so far is that, according to Chrome’s policies (as well as most other browsers), it’s impossible to play a sound on a website without user interaction (such as a click).

There are solutions based on exploits (which have stopped working), bugs, etc., but according to browser policies, videos can only autoplay without sound. However, YouTube essentially bypasses this rule and plays both video and audio automatically when a page loads. That being said:

What is the explanation?

Does YouTube have special permissions because it’s YouTube?

What is the necessary HTML/JS code to achieve the same result and autoplay video audio when the page loads?

Node.js projemde sürekli tekrar eden server hataları [closed]

Bir online sohbet uygulaması kodladım. Bu projede node.js kullandım ve glitch ile yayınladım. Ama yayınladığım glitch sayfasında mesaj atamıyordum ve sürekli “Sohbete Hoşgeldiniz” yazıyordu (Bunun nedeni uygulamaya giriş yapıldığında “Sohbete Hoşgeldiniz” yazdır diye bir kod yazmam). Daha sonra konsolu açtım ve bir sürü server hataları ile karşılaştım. Bu hataları ekstra olarak koydum. Anladığım kadarıyla server kapanıyor ve tekrar açılıyordu. Bu ise sürekli tekrar ediyordu. Bu hatayı nasıl düzeltebilirim? Cevap verirseniz sevinirim.

Sadece bir sohbet uygulaması kodlamak istedim ve böyle hatalarla karşılaştım. ChatGPT’ye de sordum ama çözemedim.

Transitioning SVG Line Position

document.addEventListener("DOMContentLoaded", (event) => {
  const hamburgerButtons = document.querySelectorAll('.hm-button');
  const hamburgerLines = [
    {
      closed: {
        x1: 13,
        x2: 37,
        y1: 13,
        y2: 13,
      },
      open: {
        x1: 13,
        x2: 37,
        y1: 37,
        y2: 13,
      }
    }, {
      closed: {
        x1: 13,
        x2: 37,
        y1: 25,
        y2: 25,
      },
      open: null,
    }, {
      closed: {
        x1: 13,
        x2: 37,
        y1: 37,
        y2: 37,
      },
      open: {
        x1: 13,
        x2: 37,
        y1: 13,
        y2: 37,
      }
    }
  ]

  const handleHamburgerClick = (event) => {
    const button = event.target.closest('.hm-button');
    const lines = button.querySelectorAll('line');
    if (!button.classList.contains('open')) {
      lines.forEach((line, idx) => {
        if (hamburgerLines[idx].open) {
          line.setAttribute('x1', hamburgerLines[idx].open.x1)
          line.setAttribute('y1', hamburgerLines[idx].open.y1)
          line.setAttribute('x2', hamburgerLines[idx].open.x2)
          line.setAttribute('y2', hamburgerLines[idx].open.y2)
        }
      });
      button.classList.add('open');
    } else {
      if (button.classList.contains('open')) {
        lines.forEach((line, idx) => {
          if (hamburgerLines[idx].closed) {
            line.setAttribute('x1', hamburgerLines[idx].closed.x1)
            line.setAttribute('y1', hamburgerLines[idx].closed.y1)
            line.setAttribute('x2', hamburgerLines[idx].closed.x2)
            line.setAttribute('y2', hamburgerLines[idx].closed.y2)
          }
        });
        button.classList.remove('open');
      }
    }
  };

  hamburgerButtons.forEach((button) => {
    button.addEventListener("click", handleHamburgerClick);
  });
});
.hm-button {
  width: 50px;
  height: 50px;
  cursor: pointer;
}

.hm-button.open .hm-line2 {
  stroke: none;
}

.hm-outline {
  x: 2px;
  y: 2px;
  width: 46px;
  height: 46px;
  rx: 4px;
  fill: none;
}

.hm-outline,
[class^="hm-line"] {
stroke-width: 4px;
stroke: black;
}

[class^="hm-line"] {
stroke-linecap: round;
transition: all 0.25s ease;
}
<svg class="hm-button" role="button">
  <rect class="hm-outline" />
  <line class="hm-line1" x1="13" x2="37" y1="13" y2="13" />
  <line class="hm-line2" x1="13" x2="37" y1="25" y2="25" />
  <line class="hm-line3" x1="13" x2="37" y1="37" y2="37" />
</svg>

I’m attempting to create a hamburger menu icon using SVG and its child elements as a way to teach myself, but I’m having trouble transitioning the line positions. The change in position is instant, rather than gradual.

What I’m trying to achieve is, the middle line disappearing, and the left point of the first and third lines swap to form an X when the svg is clicked. When it is clicked again, the lines move back and the middle one reappears. Transition doesn’t seem to work when changing the position of the lines, however.

Leaflet non-geographic map with a TileLayer

I’m working on using leaflet to render a large rectangular game map, so using a TileLayer is the only reasonable option. Unfortunately I’m having a devil of a time getting the 3 different coordinate systems (game, image, and leaflet) aligned in a reasonable way. There’s… something about this all that I’m not understanding despite having read many, many SO posts and various other sources of information about CRS.Simple, L.TileLayer, L.transformation, and etc.

Here’s roughly the code I’m working with:

// These values correspond to the bounds of the in-game map
const GAME_MIN_X = -2438281.4186383262;
const GAME_MIN_Y = -1129394.0806274635;
const GAME_MAX_X = 201600;
const GAME_MAX_Y = 504000;

// The size of the source image for the tiles
const IMG_MAX_X = 16384;
const IMG_MAX_Y = 5223;

// Maximum x/y values assuming a range starting at 0
const MAX_X = GAME_MAX_X - GAME_MIN_X;
const MAX_Y = GAME_MAX_Y - GAME_MIN_Y;

// Scale factor for the transformation, see https://gis.stackexchange.com/a/201037
const scaleX = 1 / (MAX_X / IMG_MAX_X);
const scaleY = 1 / (MAX_Y / IMG_MAX_Y);

const crs = L.extend(L.CRS.Simple, {
  transformation: L.transformation(
    scaleX,
    0,
    scaleY,
    0
  ),
});

var map = L.map('map', {
  crs,
  maxZoom: 6,
});

const tiles = L.tileLayer("https://patcavit.com/tiles/{z}/{y}/{x}.png", {
  errorTileUrl: "https://patcavit.com/tiles/blank.png",

  minNativeZoom: 0,
  maxNativeZoom: 6,
  noWrap: true,

  bounds: [
    // Using MAX_* shows a lot of blank tiles
    [MAX_Y, 0],
    [0, MAX_X],
    // Using GAME_MAX_* shows a lot of blank tiles
    // [ GAME_MAX_Y, 0 ],
    // [ 0, GAME_MAX_X ],
    // Using IMG_MAX_* leads to only one tile being shown
    // [ IMG_MAX_Y, 0 ],
    // [ 0, IMG_MAX_X ]
  ],
});

tiles.addTo(map);

map.setView([0, 0], 0);

Here’s a live, editable version

I suspect that there’s a small part of the transformation on the CRS or how I’m defining bounds on the TileLayer that is tripping up literally everything else, but I’m kind of at my wit’s ends here.

For context, the MAX_Y and MAX_X values are me trying to scope the range of my points to start from 0 because that seems to play better with the TileLayer bits, but that could just be me misunderstanding things. I’d love to not need it, as it makes turning game coordinates into map coordinates a tiny bit inconvenient.

React Testing Library: rerender creates a new component

I have this component that I am trying to test, that shows a dialog which accepts images to upload into the app:

import React from 'react';
import { Box, Typography, Dialog, DialogTitle } from '@mui/material';

import UploadBox from './UploadBox';


/**
 * An interface for uploading new images to the app.
 * 
 * @param {object} props Contains props passed to the component.
 * @param {boolean} props.open Controls open/visible state of the componenet.
 * 
 * @returns The UploadDialog componenet to be rendered in the app.
 */
function UploadDialog(props) {

    const handleClose = () => {
        props.onClose();
    };

    return(
        <Dialog open={props.open} onClose={handleClose}>
            <DialogTitle>
                Upload Media
            </DialogTitle>
            <Box sx={{margin: '0 5% 0 5%'}}>
                <Typography>
                    Drag and drop into the box, or click the button to browse
                </Typography>
                <UploadBox/>
            </Box>
        </Dialog>
    );
};

export default UploadDialog; 

Jest passes the first two tests of the suite that check if the component renders correctly both open and closed, but the third test that tried to toggle between these states fails.
Here is the test code:

import React from 'react';
import { screen, render } from '@testing-library/react';
import '@testing-library/jest-dom';

import UploadDialog from './UploadDialog';

jest.mock('./UploadBox', () => () => {<div/>});


describe('UploadDialog', () => {
    let handleClose = jest.fn();

    test('renders closed', () => {
        render(<UploadDialog open={false} handleClose={handleClose}/>);
        expect(screen.queryByRole('presentation')).not.toBeInTheDocument();
    });

    test('renders open', () => {
        render(<UploadDialog open={true} handleClose={handleClose}/>);

        // There are two presentation role elements; both should be present
        const expectedElements = screen.getAllByRole('presentation');
        expect(expectedElements[0]).toBeInTheDocument();
        expect(expectedElements[1]).toBeInTheDocument();
    });

    test('toggles open and closed', () => {
        // This piece passes
        const {rerender} = render(
            <UploadDialog open={false} handleClose={handleClose}/>
        );

        expect(screen.queryByRole('presentation')).not.toBeInTheDocument();

        // This also gets through fine
        rerender(<UploadDialog open={true} handleClose={handleClose}/>);

        const expectedElements = screen.getAllByRole('presentation');
        expect(expectedElements[0]).toBeInTheDocument();
        expect(expectedElements[1]).toBeInTheDocument();

        // This is where the problem shows up
        rerender(<UploadDialog open={false} handleClose={handleClose}/>);

        expect(screen.queryAllByRole('presentation').length).toBe(0);
    });
});

The final test fails with the following error:

UploadDialog › toggles open and closed

    expect(received).toBe(expected) // Object.is equality

    Expected: 0
    Received: 2

      50 |         rerender(<UploadDialog open={dialogOpen} handleClose={handleClose}/>);
      51 |
    > 52 |         expect(screen.queryAllByRole('presentation').length).toBe(0);
         |                                                              ^
      53 |     });
      54 | });

When using screen.debug(), I see only the open={true} version of this component. I have checked that this component is behaving correctly in the app, closing and opening when expected (as the first two tests suggest), so this seems to be a problem with React Testing Library. Does rerender only work once in React Testing Library? How do I rerender a second time?

Using Dexie inside WebSQL transaction

I’m having some trouble using Dexie inside a WebSQL transaction. It looks like Dexie closes WebSQL transaction when it’s promise is finished.

The code structure looks something like this:

AccessIndexDBThroughDexie = () => {
    return this.dexieTable.bulkPut(data);
};


Database.read( tx => {
    tx.executeFragment('SQL ...')
    .then((result) => {
        return AccessIndexDBThroughDexie(result);
    })
    .then( () => {
        return tx.executeFragment('SQL ...'); //this execution raises the error on DOM
    })
})

This throws the following error:
DOMException: Failed to execute 'executeSql' on 'SQLTransaction': SQL execution is disallowed.

I tried solving it with Dexie.transaction to see if explicitly creating a transaction for the Dexie operations it would do it, but it didn’t made any difference.
Is there a way to prevent Dexie from interfering with webSQL transactions?

Which programming langauges are backward compatible and which are forward compatible?

Which programming languages are backward compatible and which are forward compatible? I am asking this question because when I found that some languages are deprecating their features in newer version,which existed in older versions and making new code unable to mix up with old code.Why?

I need to know this because I am confused to switch between version of a particular programming language.

Problem in React using DataTable with Bootstrap5

I am using this DataTable, which works correctly, the problem is that when I run it I get this error: “DataTables warning: table id=example – Cannot reinitialise DataTable. For more information about this error, please see https://datatables.net/tn/3“, the solution was to use the following: ‘if ($.fn.DataTable.isDataTable(’#example”)) {
$(“#example”).DataTable().destroy();
}”. But now I have a new problem and I get a very wide and empty column at the end of the table, do you know how to solve it?

import React, { useEffect, useState } from "react";
import $ from "jquery";
import "datatables.net-bs5";

function MyDataTable() {
  const [users] = useState([
    {
      id: 1,
      nombre: "Axel",
      primerApellido: "Rojero",
      segundoApellido: "Flores",
      curp: "HFKJALSITOSPR9AISK",
      rfc: "DJU8ALS9F0SLD",
    },
    {
      id: 2,
      nombre: "Kira",
      primerApellido: "Garfias",
      segundoApellido: "Gonzalez",
      curp: "HFKJALSITOSPR9AISK",
      rfc: "DJU8ALS9F0SLD",
    },
  ]);

  useEffect(() => {
    if ($.fn.DataTable.isDataTable("#example")) {
      $("#example").DataTable().destroy();
    }

    $("#example").DataTable({
      autoWidth: true,
      paging: false,
      searching: true,
      colReorder: true,
      fixedHeader: true,
      responsive: true,
      stateSave: true,
      columns: [
        { title: "Numero de empleado" },
        { title: "Nombre" },
        { title: "Primer apellido" },
        { title: "Segundo apellido" },
        { title: "CURP" },
        { title: "RFC" },
        { title: "Editar" },
        { title: "Borrar" },
      ],
    });
  }, [users]);

  return (
    <div className="container mt-5">
      <h2>Docentes</h2>
      <div className="col mb-3">
        <button type="button" className="btn btn-primary">
          Agregar Usuario
        </button>
      </div>
      <table
        id="example"
        className="table table-striped table-bordered"
        style={{ width: "100%" }}
      >
        <thead>
          <tr>
            <th>Numero de empleado</th>
            <th>Nombre</th>
            <th>Primer apellido</th>
            <th>Segundo apellido</th>
            <th>CURP</th>
            <th>RFC</th>
            <th>Editar</th>
            <th>Borrar</th>
          </tr>
        </thead>
        <tbody>
          {users.map((user) => (
            <tr key={user.id}>
              <td>{user.id}</td>
              <td>{user.nombre}</td>
              <td>{user.primerApellido}</td>
              <td>{user.segundoApellido}</td>
              <td>{user.curp}</td>
              <td>{user.rfc}</td>
              <td>
                <button className="btn btn-warning">Editar</button>
              </td>
              <td>
                <button className="btn btn-danger">Borrar</button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

export default MyDataTable;

Error

DataTable pre-destruction: Used $(“#example”).DataTable().destroy() before each initialization to avoid duplication when re-rendering the table.

Use of useEffect: Table initialization is performed inside useEffect, ensuring that the table is properly destroyed before being re-created.

Disabling of certain settings: Properties such as autoWidth and responsive were disabled to eliminate possible conflicts that could be causing the duplications.

NextJS Hydration Error beacuse of `useMediaQuery` usage

I have a dynamic page like this in nextjs:

/* Imports */

async function getData(id: string) {
  const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/homework/${id}`, {
    cache: 'no-cache',
  });

  if (!res.ok) {
    throw new Error('Failed to fetch data');
  }

  return (await res.json()) as Homework;
}

export default async function HomeworkPage({
  params,
}: {
  params: { name: string };
}) {
  const data = await getData(params.name);

  return (
    <>
   /* Some client and server components */
    </>
  );
}

This page is rendered using this layout:

'use client';

import { AnnouncementBar } from '@/components/editor/components/announcement-bar';
import { Footer } from '@/components/footer';
import { HeaderApp } from '@/components/header-app';
import { QuickBar } from '@/components/ui/quick-bar';

interface AppLayoutProps {
  children: React.ReactNode;
}

export default function AppLayout({ children }: AppLayoutProps) {
  return (
    <div className='flex min-h-screen flex-col'>
      <AnnouncementBar />
      <HeaderApp />

      <main className='flex flex-1 pt-[calc(var(--announcement-bar-height)+var(--header-height))]'>
        <div className='container px-3 py-6 md:px-6'>{children}</div>
        <QuickBar />
      </main>

      <Footer />
    </div>
  );
}

Where for example in AnnounementBar I have the following logic that uses both lcoalStorage in getUserOrGuest method and useMediaQuery in useIsDesktop:

"use client"

export const AnnouncementBar = () => {
  const user = getUserOrGuest();
  const isDesktop = useIsDesktop();

  return (
    <div
      className={clsx(
        'z-[50] h-[40px] w-full border-y-[1px] border-border/90 scrolled:h-0',
        'flex items-center justify-center text-sm transition-[opacity,height] duration-200',
        'overflow-hidden scrolled:border-none scrolled:leading-[0] scrolled:opacity-0',
        'fixed left-0 top-0 bg-header p-2'
      )}
    >
      <div className='flex items-center gap-1.5'>
        <AlertTriangle className='mr-2' />
        {isDesktop && <span>Platforma jest w wersji</span>}

        <ResponsiveDialog
          trigger={
            <Button
              variant='ghost'
              className='hover:bg-initial m-0 flex gap-1 p-0 text-violet-11 hover:text-violet-12 hover:underline'
            >
              <span className='font-bold'>
                {isDesktop ? 'testowej!' : 'wersja testowa!'}
              </span>
            </Button>
          }
          title='Wersja testowa'
          content={
            <div className='flex flex-col gap-3'>
              <p>
                Ponieważ jesteśmy nowo powstałą platformą, potrzebujemy czasu
                aby przetestować wszystkie funkcjonalności oraz uzupełnić
                platformę o wartościowe treści. Do tego czasu{' '}
                <span className='font-bold text-red-10 underline underline-offset-4'>
                  rejestracja kont ucznia jest wyłączona!
                </span>
              </p>
              <p className='font-bold'>
                Jesteś nauczycielem?{' '}
                <Link className='mw-link' href='/register/teacher'>
                  Dołącz do nas!
                </Link>
              </p>
            </div>
          }
        />
      </div>
      {user && (
        <Link
          className='ml-5 whitespace-nowrap font-bold text-red-10 hover:text-red-11'
          href='/feedback'
        >
          Zgłoś błąd lub sugestię
        </Link>
      )}
    </div>
  );
};

The problem is that for some reason this component is server side rendered and then I have a hydration error because when I reload page, initially the mobile view is rendered and user is null and then it is replaced by the proper view (user is taken from localStorage and isDesktop is false). I don’t really get why is that a case. Any ideas?