why loader function not called in react js?

I am using React-Router-DOM loader prop function (https://reactrouter.com/en/main/route/loader).

<BrowserRouter>
  <Routes>
    <Route
      path={'/ap'}
      loader={() => {
        console.log('0000');
        return 'ss';
      }}
      element={<App />}
    ></Route>
  </Routes>
</BrowserRouter>

When I check on console it is not called or in other words message is not printed.

Here is my code: https://stackblitz.com/edit/vitejs-vite-6gg4ab?file=src%2FApp.tsx,src%2Fmain.tsx&terminal=dev

function App() {
  const [count, setCount] = useState(0);
  const data = useLoaderData();
  console.log('----s', data);
  return (
    <>
      <div>
        <a href="https://vitejs.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
    </>
  );
}

I am trying to fetch some data before routing and I don’t know what I am doing wrong.

Fetch API Skipping .then() Block After POST Request in Node.js: JSON Response Not Processed

I’m using the fetch API in my JavaScript code to make a POST request to a specific endpoint. However, I’m encountering an issue where the fetch call seems to skip the .then() block entirely and goes straight to a return false statement. Here’s a simplified version of my code:

function login() {
    var emailVar = email_input.value;
    var senhaVar = senha_input.value;

    if (emailVar == "" || senhaVar == "") {
        return false;
    }

    console.log("FORM LOGIN: ", emailVar);
    console.log("FORM SENHA: ", senhaVar);

    fetch("/usuario/autenticar", {
        method: "POST",
        headers: {
            "Content-Type": "application/json"
        },
        body: JSON.stringify({
            emailServer: emailVar,
            senhaServer: senhaVar
        })
    }).then(function (resposta) {
        console.log("HERE'S IS THEN()!")

        if (resposta.ok) {
            console.log(resposta);


            resposta.json().then(json => {
                console.log(json);
                console.log(JSON.stringify(json));
                sessionStorage.EMAIL_USUARIO = json.email;
                sessionStorage.NOME_USUARIO = json.nome;
                sessionStorage.ID_USUARIO = json.id;

            });

        } else {

            console.log("login error");

            resposta.text().then(texto => {
                console.error(texto);
            });
        }

    }).catch(function (erro) {
        console.log(erro);
    })
    return false;
}

The strange behavior I’m experiencing is that after the fetch call, specifically when it reaches the body: JSON.stringify(…) part, it goes straight to the return false statement without entering the .then() or .catch() blocks. I’ve checked the Network tab in my browser’s developer tools, and the request seems to be sent successfully with the expected JSON body.

I’m not sure why the fetch call is behaving this way and skipping the .then() block. Any insights or suggestions would be greatly appreciated. Thank you!

What I expected to happen was that after the fetch call, it would enter the .then() block, parse the JSON response, and set some session storage variables. However, what actually happened is that it skipped the .then() block entirely and went straight to the return false statement.

I’ve checked the Network tab in my browser’s developer tools, and the request seems to be sent successfully with the expected JSON response. The strange behavior is that the .then() block is not being executed at all.

My socket.io server code isn’t running when everything else is

I’m going to preface this by saying, I’m not that great at coding, so sorry if my code is bad.

What I’m trying to do is make an socket.io server, but I’m having trouble with the server code not running for some reason. Everything else runs, but not index.js.
Index.html:

<!doctype html>
<html>
        
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>Thingie</title>
    <link rel="stylesheet" href="style.css">
  </head>
        
  <body>
    <div class="title" id="title">
        Idk
    </div>
    <script src="/socket.io/socket.io.js"></script>
    <script src="script.js"></script>
  </body>
        
</html>

script.js:

const socket = io();

io.on("Hello", (msg) => {
    alert(msg)
});

index.js:

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/public/index.html');
});

io.on('connection', (socket) => {
  socket.emit("Hello", "Hi")
});

server.listen(3000, () => {
  console.log('listening on *:3000');
});

I have tried following the socket.io tutorial on their website, but that didn’t help me very much. I tried adding to the html hoping that it would run index.js, but that didn’t do anything either.

Firestore query with multiple where()

Im trying to get a single document from a collection in firestore, but its document id has to be diferent from a list of ids on an array

const excludedIds = ["zyYjPcJG0mqy3WXDQBOZ", "Dics6F0gKPtxKqOuxIhm"];

 const getPotentialMatch = async () => {
    const petsCollection = firestore().collection("pets");
    let query = petsCollection.where("type", "==", "dog");

    excludedIds.forEach((id) => {
      query = query.where(firestore.FieldPath.documentId(), "!=", id);
    });

    query = await query.get();

    let potentialMatches = query.docs.map((doc) => ({
      id: doc.id,
      ...doc.data(),
    }));

    console.log(potentialMatches);
  };

The problem is that firestore does not allow me to do more than one where() with ‘!=’, so i need another way for achieving this, but only fetching one document at a time

Javascript Jose Sign And Encrypt JWT

I am using jose to sign and encrypt JWTs. However I am unable to sign and then encrypt my whole JWT.

I use this function to sign my jwt:

const secretKey = process.env.JWT_SECRET;
const key = new TextEncoder().encode(secretKey);

export async function _encrypt(payload: any) {
  return await new SignJWT(payload)
    .setProtectedHeader({ alg: "HS256" })
    .setIssuedAt()
    .setExpirationTime("10 sec from now")
    .sign(key);
}

I am using following code to encrypt it (when passing an JWT object it works):

const now = () => (Date.now() / 1000) | 0;

const alg = "dir";
const enc = "A256CBC-HS512";

...

sync function encrypt({
  payload,
  maxAge,
}: {
  payload: JWTPayload;
  maxAge: number;
}): Promise<string> {
  const secret: Uint8Array = randomBytes(32);
  const salt = randomBytes(16);
  const encryptionSecret: Uint8Array = await hkdf(
    "sha256",
    secret,
    salt,
    "Generated Encryption Key",
    32
  );
  
  return new EncryptJWT(payload)
    .setProtectedHeader({ alg, enc })
    .setIssuedAt()
    .setExpirationTime(now() + maxAge)
    .setJti(crypto.randomUUID())
    .encrypt(encryptionSecret);
}

The code does not work as intended because EncryptJWT does only accept an JWT object. This is also reflected in the console: error TypeError: JWT Claims Set MUST be an object

Tryed to make makers.Too many re-renders. React limits the number of renders to prevent an infinite loop

I ama developping a react native app of EXPO.
I have just faced an error below.

Too many re-renders. React limits the number of renders to prevent an infinite loop.

I will get jissaitoretatoomou? [{“latitude”: 35.52400475291494, “longitude”: 139.4506602713825, “user_id”: 0}]
and render s with latitude and longitude for each element.”

import React, { useState, useEffect } from "react";
import { View, Text, ScrollView, StyleSheet, TextInput, Button ,Switch,Dimensions,Image} from "react-native";
import { useNavigation } from '@react-navigation/native'; // useNavigationを追加
import MapView, { Marker ,Polyline} from 'react-native-maps';
import {requestLocationPermission,getCurrentLocation,writeMyLocationData} from '../../sockets/googlemap'
import {findPlace,fetchRoute} from '../../sockets/googleroute'
import { ref,onChildAdded} from "firebase/database";
import { database } from '../../firebaseConfig'; // Firebaseのデータベースを正しくインポートする必要があります



const Main = () => {
        const [otherRiders, setOtherRiders] = useState([]);
 
    const dbref = ref(database); //取得したいデータのパスを指定
    onChildAdded(dbref, function (snapshot) {
        let data = snapshot.val();
        setOtherRiders(data)
        console.log("jissaitoretatoomou?",data);
});
    console.log("kakunin",otherRiders)
    const [routeInfo, setRouteInfo] = useState({ origin: "", destination: "" });
    const navigation = useNavigation(); // useNavigationフックを使用してnavigationオブジェクトを取得
    const [myCurrentLocation,setMyCurrentLocation] = useState({
        latitude: 0,
        longitude: 0,
    })
    const [myDestination,setMyDestination] = useState({
        latitude: 0,
        longitude: 0,
    })
    const [myOrigin,setMyOrigin] = useState({
        latitude: 0,
        longitude: 0,
    })
    // DB を取得している
    
    const [isMapReady, setIsMapReady] = useState(false);
    const [isEnabled, setIsEnabled] = useState(false);
    const toggleSwitch = () => setIsEnabled(previousState => !previousState);
    const iconImage = require('../../assets/kurumi.jpg');
    const myDestinationIcon = require('../../assets/flag.png');

    // requestLocationPermission();
    useEffect(() => {
        requestLocationPermission(setMyCurrentLocation,myCurrentLocation,setIsMapReady);
        
    });

    return (
        isMapReady ? ( // マップが準備完了したら表示
        <ScrollView  style={styles.Wrapper}>
            
                <View style={styles.mapContainer}>
                    <MapView style={styles.map}
                        initialRegion={{
                            latitude: myCurrentLocation.latitude,
                            longitude: myCurrentLocation.longitude,
                            latitudeDelta: 0.0922,
                            longitudeDelta: 0.0421,
                        }}
                    >
                        <Marker
                            coordinate={{
                                latitude: myCurrentLocation.latitude,
                                longitude: myCurrentLocation.longitude,
                            }}
                        >
                            <Image style={styles.icon} source={iconImage} />
                        </Marker>
                        <Marker
                            coordinate={{
                                latitude: myDestination.latitude,
                                longitude: myDestination.longitude,
                            }}
                        >
                            <Image style={styles.icon} source={myDestinationIcon} />
                        </Marker>
                            <Polyline
                            coordinates={[
                                { latitude: myOrigin.latitude, longitude: myOrigin.longitude },
                                { latitude: myDestination.latitude, longitude: myDestination.longitude },
                            ]}
                            strokeColor="#FF0000" // 線の色
                            strokeWidth={2} // 線の太さ
                        />


                    </MapView>
                </View>                
            <View>
                <Text style={styles.direction}>出発地</Text>
                <TextInput
                    placeholder={'出発地を入力してください'}
                    value={routeInfo.origin}
                    autoCapitalize="none"
                    onChangeText={text => setRouteInfo({ ...routeInfo, origin: text })} // オブジェクトをスプレッドして、originプロパティのみを更新
                    style={styles.imputBox}
                />
            </View>
            <View>
                <Text style={styles.direction}>目的地</Text>
                <TextInput
                    placeholder={'到着地を入力してください'}
                    value={routeInfo.destination}
                    autoCapitalize="none"
                    onChangeText={text => setRouteInfo({ ...routeInfo, destination: text })} // オブジェクトをスプレッドして、destinationプロパティのみを更新
                    style={styles.imputBox}
                />
            </View>
            <View>
                <Button
                    title="ルートを検索する"
                    onPress={() => fetchRoute(setMyOrigin,setMyDestination,routeInfo)}
                />
            </View>
            <View>
                <Text style={styles.infomation}>位置情報共有をONにする</Text>
                <Switch
                    trackColor={{false: '#767577', true: '#81b0ff'}}
                    thumbColor={isEnabled ? '#f5dd4b' : '#f4f3f4'}
                    ios_backgroundColor="#3e3e3e"
                    onValueChange={toggleSwitch}
                    value={isEnabled}
                />
            </View>
            <View>
                <Button
                    title="戻る"
                    onPress={() => navigation.navigate('Top')}
                />
            </View>
        </ScrollView>
        ):<ScrollView style={styles.waitScrollViewContent}><View style={styles.center}><Text style={styles.infomation}>少々お待ちください。。。</Text></View></ScrollView>
    )
}

export default Main;

const { height } = Dimensions.get("window");
const mapHeight = height * 0.5; // 画面の半分の高さ
const styles = StyleSheet.create({
    Wrapper:{
        flex: 1, // 画面の半分のサイズに設定
    },
    direction: {
        fontSize: 12,
        padding:10
    },
    infomation: {
        fontSize: 12,
        padding:10
    },
    subTitle: {
        fontSize: 14,
        textAlign: "center",
        padding:5
    },
    mapContainer: {
        height: mapHeight,
        justifyContent: 'center',
        alignItems: 'center',
    },
    map: {
        ...StyleSheet.absoluteFillObject,
    },
    markerContainer: {
        backgroundColor: 'blue',
        padding: 5,
        borderRadius: 5,
    },
    markerText: {
        color: 'white',
        fontWeight: 'bold',
    },
    imputWrapper: {
        alignItems: "center", // 横方向に中央揃え
        padding: 20
    },
    imputContainer:{
        width:'100%',
        marginBottom:10
    },
    imputBox: {
        height: 40,
        borderWidth: 1,
    },
    icon: {
      width: 28,
      height: 28,
    },
    waitScrollViewContent: {
    flex: 1,
    width:'100%',
  },
    center: {
    flex: 1,
        justifyContent: 'center',
        alignItems: 'center',

    },
});

i tryed to write onChildAdded between useEffect
i tryed to write callback into setIntervel

Issue in rendering D3 heatmap for grouped data

I need to render a heatmap with y labels on Y-axis, x labels on bottom X-axis and groups on top X-axis
each group has different number of days.In my dataset i have 36 objects, I’m supposed to see 36 rectangles

import { useMemo } from "react";
import * as d3 from "d3";

const MARGIN = { top: 50, right: 50, bottom: 50, left: 50 };

type HeatmapProps = {
  width: number;
  height: number;
  data: { x: number; y: string; group: string; value: number }[];
};
  data = [
  { group: "A", y: "Apple", x: 0, value: 68 },
  { group: "A", y: "Orange", x: 0, value: 45 },
  { group: "A", y: "Grapes", x: 0, value: 43 },
  { group: "A", y: "Apple", x: 1, value: 58 },
  { group: "A", y: "Orange", x: 1, value: 85 },
  { group: "A", y: "Grapes", x: 1, value: 23 },
  { group: "A", y: "Apple", x: 2, value: 58 },
  { group: "A", y: "Orange", x: 2, value: 45 },
  { group: "A", y: "Grapes", x: 2, value: 53 },
  { group: "A", y: "Apple", x: 3, value: 58 },
  { group: "A", y: "Orange", x: 3, value: 45 },
  { group: "A", y: "Grapes", x: 3, value: 53 },
  { group: "B", y: "Apple", x: 1, value: 70 },
  { group: "B", y: "Orange", x: 1, value: 52 },
  { group: "B", y: "Grapes", x: 1, value: 65 },
  { group: "B", y: "Apple", x: 2, value: 70 },
  { group: "B", y: "Orange", x: 2, value: 52 },
  { group: "B", y: "Grapes", x: 2, value: 65 },
  { group: "B", y: "Apple", x: 3, value: 70 },
  { group: "B", y: "Orange", x: 3, value: 52 },
  { group: "B", y: "Grapes", x: 3, value: 65 },
  { group: "C", y: "Apple", x: 1, value: 48 },
  { group: "C", y: "Orange", x: 1, value: 46 },
  { group: "C", y: "Grapes", x: 1, value: 65 },
  { group: "C", y: "Apple", x: 2, value: 48 },
  { group: "C", y: "Orange", x: 2, value: 46 },
  { group: "C", y: "Grapes", x: 2, value: 65 },
  { group: "C", y: "Apple", x: 3, value: 48 },
  { group: "C", y: "Orange", x: 3, value: 46 },
  { group: "C", y: "Grapes", x: 3, value: 65 },
  { group: "C", y: "Apple", x: 4, value: 48 },
  { group: "C", y: "Orange", x: 4, value: 46 },
  { group: "C", y: "Grapes", x: 4, value: 65 },
  { group: "C", y: "Apple", x: 5, value: 48 },
  { group: "C", y: "Orange", x: 5, value: 46 },
  { group: "C", y: "Grapes", x: 5, value: 65 },
];

export const Heatmap = ({ width, height, data }: HeatmapProps) => {
  // bounds = area inside the axis
  const boundsWidth = width - MARGIN.right - MARGIN.left;
  const boundsHeight = height - MARGIN.top - MARGIN.bottom;

  // Groups
  const yData = useMemo(() => [...new Set(data.map((d) => d.y))], [data]);
  const xGroups = useMemo(() => [...new Set(data.map((d) => d.group))], [data]);

  const [min, max] = d3.extent(data.map((d) => d.value));

  if (!min || !max) {
    return null;
  }

  // Color scale
  const colorScale = d3
    .scaleSequential()
    .interpolator(d3.interpolateInferno)
    .domain([min, max]);

  // Y scale
  const yScale = d3
    .scaleBand()
    .domain(yData)
    .range([0, boundsHeight])
    .padding(0.01);

  // Group elements
  const groupElements = xGroups.map((group, i) => {
    const groupData = data.filter((d) => d.group === group);
    const days = [...new Set(groupData.map((d) => d.x))];

    // X scale for the group
    const xScale = d3
      .scaleBand()
      .range([0, boundsWidth])
      .domain(days)
      .padding(0.01);

    // Rectangles for the group
    const rects = days.map((day, j) => {
      const dayData = groupData.filter((d) => d.x === day);
      return dayData.map((d, k) => (
        <rect
          key={`rect-${group}-${day}-${k}`}
          x={xScale(day)}
          y={yScale(d.y)}
          width={xScale.bandwidth()}
          height={yScale.bandwidth()}
          fill={colorScale(d.value)}
          rx={5}
          stroke={"white"}
        />
      ));
    });

    // X labels for the group
    const xLabels = days.map((day, j) => (
      <text
        key={`${group}-${day}`}
        x={xScale(day) + xScale.bandwidth() / 2}
        y={boundsHeight + MARGIN.bottom / 2}
        textAnchor="middle"
        dominantBaseline="middle"
        fontSize={10}
      >
        {day}
      </text>
    ));

    // Group label
    const groupLabel = (
      <text
        key={`label-${group}`}
        x={boundsWidth / 2}
        y={boundsHeight + MARGIN.bottom - 10}
        textAnchor="middle"
        dominantBaseline="middle"
        fontSize={10}
      >
        {group}
      </text>
    );

    return (
      <g
        key={`group-${group}`}
        transform={`translate(0, ${i * (boundsHeight + MARGIN.bottom)})`}
      >
        {rects}
        {xLabels}
        {groupLabel}
      </g>
    );
  });

  // Y labels
  const yLabels = yData.map((name, i) => (
    <text
      key={i}
      x={-5}
      y={yScale(name) + yScale.bandwidth() / 2}
      textAnchor="end"
      dominantBaseline="middle"
      fontSize={10}
    >
      {name}
    </text>
  ));

  return (
    <div>
      <svg width={width} height={height}>
        <g transform={`translate(${MARGIN.left}, ${MARGIN.top})`}>
          {yLabels}
          {groupElements}
        </g>
      </svg>
    </div>
  );
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>

i’m only seeing heatmap rectangles for first group A
Based upon my data, I should see 36 rectangles with x values as X labels grouped by group labels

Implementing JavaScript in Shiny Modules

I have a shiny app which generates trend lines of a timeseries data. In the app its using JavaScript code to get the Time zone so that it can be used to make sure the timeseries data can be converted to local time zone.

Problem :
Trend Line is not showing but in the browser console : Time Zone is being displayed.

Below is the Sample Code :

library(shiny)
library(shinyjs)
library(plotly)
library(dplyr)
library(lubridate)

# JavaScript code
jsCode <- '
shinyjs.getClientTimezone = function() {
  const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
  Shiny.setInputValue("client_timezone", timezone);
  console.log("Client Timezone", timezone);
}'

# Module UI
mod_trend_chart_ui <- function(id) {
  ns <- NS(id)
  tagList(
    shinyjs::useShinyjs(),
    shinyjs::extendShinyjs(text = jsCode, functions = "getClientTimezone"),
    plotlyOutput(ns("trend_chart"))
  )
}

# Module Server
mod_trend_chart_server <- function(id, raw_data, processed_data) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns
    
    observe({
      shinyjs::runjs(jsCode)
      shinyjs::js$getClientTimezone()
    })
    
    client_timezone <- reactive({
      req(input$client_timezone)
      print(paste("Received client timezone:", input$client_timezone))
      input$client_timezone
    })
    
    observe({
      print(client_timezone())
    })
    
    output$trend_chart <- renderPlotly({
      timezone <- client_timezone()
      req(timezone)
      
      raw <- raw_data()
      processed <- processed_data()
      
      if (nrow(raw) == 0 && nrow(processed) == 0) {
        return(plot_ly() %>%
                 layout(title = "No data available."))
      } else {
        p <- plot_ly() %>%
          add_trace(
            data = raw, x = ~utc_timestamp, y = ~value, name = "Raw Data", type = "scatter", mode = "lines",
            line = list(color = "#f69a8e", shape = "hv"),
            hovertemplate = "Timestamp:%{x}<br>Value:%{y:.2f}"
          ) %>%
          add_trace(
            data = processed, x = ~utc_timestamp, y = ~value, name = "Processed Data", type = "scatter", mode = "lines",
            line = list(color = "#6bbcf3", shape = "hv"),
            hovertemplate = "Timestamp:%{x}<br>Value:%{y:.2f}"
          )
        
        return(p)
      }
    })
  })
}

# Sample data
raw_data_sample <- data.frame(
  utc_timestamp = as.POSIXct(c("2023-06-01 10:00:00", "2023-06-01 11:00:00", "2023-06-01 12:00:00")),
  value = c(10, 20, 30)
)

processed_data_sample <- data.frame(
  utc_timestamp = as.POSIXct(c("2023-06-01 10:00:00", "2023-06-01 11:00:00", "2023-06-01 12:00:00")),
  value = c(15, 25, 35)
)

# Main UI
ui <- fluidPage(
  mod_trend_chart_ui("trendChart")
)

# Main Server
server <- function(input, output, session) {
  raw_data <- reactiveVal(raw_data_sample)
  processed_data <- reactiveVal(processed_data_sample)
  
  mod_trend_chart_server("trendChart", raw_data, processed_data)
}

# Run the app
shinyApp(ui, server)

Tanstack Table infinite table whenever the pagination or sorting changes

So I am trying to build a reusable Table component using Tanstack Table.

import { Box, Stack } from '@mui/material';
import type { SortingState, OnChangeFn, PaginationState } from '@tanstack/react-table';

import {
  useReactTable,
  getCoreRowModel,
  flexRender,
  getSortedRowModel,
  getPaginationRowModel,
} from '@tanstack/react-table';
import Text from '@components/Text';
import SortIconTable from '@components/SortIconTable';
import { useMemo, useState } from 'react';

export type PaginationShape = {
  cursor?: string | null | undefined;
  page: number;
  pageSize: number;
};

export type TableProps<TData> = {
  columns: TData[];
  cursor?: string | null | undefined;
  loading?: boolean;
  onPagination?: OnChangeFn<PaginationShape>;
  onSort?: OnChangeFn<SortingState>;
  pagination?: PaginationState;
  rows: TData[];
};

export type TablePropsColumns<TData> = TableProps<TData>['columns'];
const pageSizes = [10, 20, 50, 100, 500];

export const Table = ({ rows, columns, onSort, onPagination, cursor }: TableProps<any>) => {
  const [sorting, setSorting] = useState<SortingState>([]);
  const [pagination, setPagination] = useState<PaginationState>({ pageIndex: 0, pageSize: 10 });

  const memoizedRows = useMemo(() => rows, [rows]);
  const memoizedColumns = useMemo(() => columns, [columns]);

  const table = useReactTable({
    autoResetPageIndex: true,
    columnResizeMode: 'onChange',
    columns: memoizedColumns,
    data: memoizedRows,
    debugColumns: true,
    debugHeaders: true,
    debugTable: true,
    enableColumnFilters: true,
    enableColumnResizing: true,
    enableMultiSort: false,
    getCoreRowModel: getCoreRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    manualPagination: true,
    manualSorting: true,
    onPaginationChange: async updater => {
      if (typeof updater !== 'function') return;

      const newPageInfo = await updater(table.getState().pagination);
      setPagination(() => newPageInfo);

      const formatPaginationData = {
        cursor,
        page: newPageInfo?.pageIndex,
        pageSize: newPageInfo?.pageSize,
      };

      onPagination?.(formatPaginationData);
    },
    onSortingChange: data => {
      setSorting(data);
      onSort?.(data);
    },
    sortDescFirst: false,
    state: {
      pagination,
      sorting,
    },
  });

  return (
    <div className="p-2">
      <Box sx={{ position: 'relative' }}>
        <table style={{ maxWidth: '100%' }}>
          <thead>
            {table.getHeaderGroups().map(headerGroup => (
              <tr key={headerGroup.id}>
                {headerGroup.headers.map(header => {
                  const canResize = header.column.getCanResize();
                  const canSort = header.column.getCanSort();
                  return (
                    <th colSpan={header.colSpan} key={header.id} style={{ width: header.getSize() }}>
                      <Stack direction={'row'}>
                        {flexRender(header.column.columnDef.header, header.getContext())}
                        {canSort && (
                          <SortIconTable
                            onSort={() => {
                              table.setSorting([
                                {
                                  desc: !header.column.getIsSorted(),
                                  id: header.column.id,
                                },
                              ]);
                              header.column.getToggleSortingHandler();
                            }}
                            sortDirection={header.column.getNextSortingOrder()}
                          />
                        )}
                        {canResize && (
                          <Box
                            className={`resizer ${header.column.getIsResizing() && 'isResizing'}`}
                            onDoubleClick={() => header.column.resetSize()}
                            onMouseDown={header.getResizeHandler()}
                            sx={{
                              '&.isResizing': {
                                background: 'blue',
                                cursor: 'col-resize',
                                opacity: 1,
                              },
                              '&:hover': {
                                cursor: 'col-resize',
                              },
                              border: '1px solid gray',
                              ml: 'auto',
                            }}
                          />
                        )}
                      </Stack>
                    </th>
                  );
                })}
              </tr>
            ))}
          </thead>
          <tbody>
            {table.getRowModel().rows.map(row => (
              <tr key={row.id}>
                {row.getVisibleCells().map(cell => (
                  <td key={cell.id} style={{ width: cell.column.getSize() }}>
                    <Text>{flexRender(cell.column.columnDef.cell, cell.getContext())}</Text>
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
          <div>
            <select
              onChange={e => {
                table.setPagination({
                  pageIndex: 0,
                  pageSize: Number(e.target.value),
                });
              }}
              value={table.getState().pagination.pageSize}
            >
              {pageSizes.map(pageSize => (
                <option key={pageSize} value={pageSize}>
                  {pageSize}
                </option>
              ))}
            </select>
          </div>
        </table>
      </Box>
    </div>
  );
};

and I am using as follow

const [sorting, setSorting] = useState<SortingState>([]);
  const [pagination, setPagination] = useState<PaginationShape>({ page: 0, pageSize: 10 });

  const params = {
    order_by: buildSortByString(sorting),
    page_size: pagination.pageSize,
  };

  console.log({ params });
  const { data } = useQuery<EventsLogResponse>({
    queryFn: () => getEventsLog({ params }),
    queryKey: ['getEventsLog', { params }],
  });

<CustomTable 
   columns={customColumns}
   cursor={data?.pagination_information.next_cursor}
   onPagination={setPagination}
   onSort={setSorting}
   rows={data?.events ?? []}
/>

I cant identify why, every time I update either the sorting or the pagination it starts an infinite loop.
Any suggestions where the root cause is coming from?

I did try to clean up the state updates on both the Table component, or in the component calling the table, but the issue seems to be coming from within the table itself.
I also thought it was a memo issue, and I added these two lines

const memoizedRows = useMemo(() => rows, [rows]);
  const memoizedColumns = useMemo(() => columns, [columns]);

but the problem still the same.

Use Javascript to download csv data from github, filter it by userID and display questions in table

I am trying to run questions in a qualtrics survey that have tables with information based on the respondent’s userID. I want to download an external CSV file from a github into the javascript, filter it by the userID of the respondent, and then display the information contained in that user’s row in a table for the question. I’m a complete beginner to JS, so I hope this makes sense!

My code, which doesn’t work, is the following:


Qualtrics.SurveyEngine.addOnload(function() {

    // Fetch the CSV data from GitHub

    fetch('https://raw.githubusercontent.com/username/repo/main/data.csv')

        .then(response => {

            if (!response.ok) {

                throw new Error('Failed to fetch CSV data');

            }

            return response.text(); 

        })

        .then(csvData => {

            // Parse CSV data into JSON format

            const parsedData = parseCsvData(csvData);

 

            // Get current respondent's userID and conjoint task number

            const userID = "${e://Field/userID}"; 

            const taskNumber = 1 // set to 1 for first task as example, since there are multiple tasks per respondent

 

            // Find matching attributes for the current respondent

            const matchingAttributes = parsedData.find(entry => entry.userID === userID && entry.task === Number(taskNumber));

 

            if (matchingAttributes) {

                // Populate table with matching attributes

                populateTable(matchingAttributes);

            } else {

                console.error('Matching attributes not found for current respondent');

            }

        })

        .catch(error => {

            console.error('Error fetching or processing CSV data:', error);

        });

 

    // Function to parse CSV data into JSON format

    function parseCsvData(csvData) {

        const rows = csvData.split('n');

        const headers = rows[0].split(',');

        const jsonData = [];

 

        for (let i = 1; i < rows.length; i++) {

            const rowData = rows[i].split(',');

            if (rowData.length === headers.length) {

                const entry = {};

                for (let j = 0; j < headers.length; j++) {

                    entry[headers[j].trim()] = rowData[j].trim();

                }

                jsonData.push(entry);

            }

        }

 

        return jsonData;

    }

 

    // Function to populate table with attributes

    function populateTable(attributes) {

        const attributeKeys = [ainfo1, ainfo2, ainfo3, ainfo4, ainfo5, ainfo6];

 

        // Update table cells with matched attributes

        for (let i = 0; i < attributeKeys.length; i++) {

            const attributeName = attributeKeys[i];

            const attributeValue = attributes[attributeName];

 

            const elementIdA = 'a' + (i + 1);

            const elementIdB = 'b' + (i + 1);

 

            // Set HTML content for candidate A and B in the table

            document.getElementById(elementIdA).innerHTML = attributeValue;

            document.getElementById(elementIdB).innerHTML = attributeValue;

        }

 

        // Store attributes as embedded data (if needed)

        const traitsA = attributeKeys.map(key => attributes[key]).join('|');

        Qualtrics.SurveyEngine.setEmbeddedData('traits1a', traitsA);

        Qualtrics.SurveyEngine.setEmbeddedData('traits1b', traitsB);

 

        // Additional embedded data

        Qualtrics.SurveyEngine.setEmbeddedData(info_data, category);

        

    }

});


 

Qualtrics.SurveyEngine.addOnUnload(function()

{

/*Place your JavaScript here to run when the page is unloaded*/

 

});

 

Where data.csv is a csv file with the following columns: userID (qualtrics userIDs for each respondent), ainfo1, ainfo2, ainfo3, ainfo4, ainfo5, ainfo6, binfo1, binfo2, binfo3, binfo4, binfo5, binfo6.

How can I download this data, filter it by respondent and display it in a table for the question? Also, how can I test this to ensure it works? Can I just supply a fake userID to the data.csv file that matches my account and then test with survey preview?

Changing js sorting criteria on a set of user created items

I have this code which allows to create, via an input form, a list of items (contracts).

It creates this:

list of sorted items

The items closest to the left are the parent ones and the other are the childs. Well, as it is now, they are sorted due to the date of the “cdate” value, being the later placed on top. The numbers shown (No. 2, No.1, etc) are dynamically assigned just to keep an order.

Example, if the first parent item created has a date, let’s say, April the first 2024, and the second is April 12 2024, then the second goes to top and adquires No. 1 and the firstly created goes to second place. With the child items happens the same, they are sorted below the parent which “cdate” value is inmediately older than its own “cdate” value and the same criteria applies to all the childs created between to parent dates. When adding an item you are able to switch which kind of item you are going to create, a parent or a child.

form for parent and for child

Above is the form. At the left, to create a parent item. At the right, switched to create a child item as it is an unique form for both items.

This is the form below.

<ul>
    <li><div class="item-content">
        <div class="item-inner">
            <div class="item-subtitle">¿Suplemento?</div>
            <div class="item-after">
            <label class="label-switch"><b class="hidden">Escoger si es suplemento</b>
                <input id="isEvolution" type="checkbox"/>
                <div class="checkbox"></div>
            </label>
            </div>
            </div>
        </div>
    </li>
    <li>
    <div id="sens2" class="sensitivefield">
    <div class="item-content">
        <div class="item-inner">
            <div class="item-input"><label for="cname">Nombre del Contrato</label>
            <input id="cname" type="text" placeholder="* Nombre del Contrato" required value="{{model.cname}}"/>
            </div>
        </div>
    </div>
    </div>
    </li>
    <li>
    <div id="sens3" class="sensitivefield" style="display:none">
    <div class="item-content">
        <div class="item-inner">
            <div class="item-input"><label for="sname">Nombre del Suplemento</label>
            <input id="sname" type="text" placeholder="* Nombre del Suplemento" required value="{{model.sname}}"/>
            </div>
        </div>
    </div>
    </div>
    </li>
    <li>
    <div class="item-content">
        <div class="item-inner">
            <div class="item-input"><label for="cdate">Fecha</label>
            <input id="cdate" type="date" placeholder="* Fecha" required value="{{model.cdate}}"/>
            </div>
        </div>
    </div>
    </li>
    <li>
    <div class="item-content">
        <div class="item-inner">
            <div class="item-input"><label for="cnumber">Número del Contrato</label>
            <input id="cnumber" type="text" placeholder="* Número del Contrato" required value="{{model.cnumber}}"/>
            </div>
        </div>
    </div>
    </li>
    <li>
        <div class="item-content">
            <div class="item-subtitle">Vigencia</div>
        </div>
    <li>
    <div class="item-content">
        <div class="item-inner">
            <div class="item-input">
            <label for="sdate">Desde</label>
            <input id="sdate" type="date" placeholder="* Desde" required value="{{model.sdate}}"/>
            <label for="ldate">Hasta</label>
            <input id="ldate" type="date" placeholder="* Hasta" required value="{{model.ldate}}"/>
            </div>
        </div>
    </div>
    </li>
    <li><div id="sens1" class="sensitivefield">
        <div class="item-content">Objeto del Contrato</div>
    <div class="item-content">
        <div class="item-inner">
            <div class="item-input"><label class="hidden" for="cobject">Objeto del Contrato</label>
            <textarea class="resizable" id="cobject" placeholder="* Objeto del Contrato"></textarea>
            </div>
        </div>
    </div>
    </div>
    </li>
    <li>
    <div class="item-content">
        <div class="item-inner">
            <div class="item-input"><label for="cvalue">Valor del Contrato</label>
            <input id="cvalue" type="number" step="any" placeholder="* Valor del Contrato" required value="{{model.cvalue}}"/>
            </div>
        </div>
    </div>
    </li>
</ul>

Here is the html code which displays the result:

<ul>
    {{#each apps}}
        <li class="accordion-item">
            <a href="#" class="item-content item-link" aria-label="Ver contrato">
                <div class="item-media">
                    {{#if isEvolution}}<i class="icon simbicon-evolution" style="margin-left:25px" aria-hidden="true"></i>{{/if}}
                    {{#unless isEvolution}}<i class="icon simbicon-contract" aria-hidden="true"></i>{{/unless}}
                </div>
                    {{#unless isEvolution}}<div class="item-inner"><div class="item-title"><b>No. {{idL}}: </b>{{cname}}</div></div></a>{{/unless}}
                    {{#if isEvolution}}<div class="item-inner"><div class="item-title"><b>No. {{idL}}: </b>{{sname}}</div></div></a>{{/if}}
            <div class="accordion-item-content">
            <div class="list-group">
            <div class="item-content">
                <div class="item-inner">
                    <div class="item-subtitle">Fecha: {{cdate}}</div>
                </div>
            </div>
            <div class="item-content">
                <div class="item-inner">
                    <div class="item-subtitle">Número: {{cnumber}}</div>
                </div>
            </div>
            <div class="item-content">
                <div class="item-inner">
                    <div class="item-subtitle">Vigencia:<br/>desde {{sdate}}<br/>hasta {{ldate}}</div>
                </div>
            </div>
            <div class="item-content">
                <div class="item-inner">
                    <div class="item-subtitle">Objeto: {{cobject}}</div>
                </div>
            </div>
            <div class="item-content">
                <div class="item-inner">
                    <div class="item-subtitle">Valor: {{cvalue}}.00 CUP</div>
                </div>
            </div>
            <br/><br/>
        </li>
    {{/each}}
</ul>

This is the js code which sorts the items:

Client.prototype.getFullAppointments2 = function() {
    var theApps=this.contracts;
    var theApps2=[];
    var currentInApp=null;
    var firstTime=true;
    var counterI=0;
    var counterE=0;
    var item=null;
    theApps.sort(appsSortCre); //appsSortCre  appsSortDec
    for (var i = 0, len = theApps.length; i < len; i++) {
        item = theApps[i];
        if (item.isEvolution==0) {
            if (firstTime) {
                firstTime=false;
                currentInApp=item;
            }else{
                counterE=0;
                counterI++;
                currentInApp.idL=counterI;
                theApps2.push(currentInApp);
                currentInApp=item;
            }

        }else{
            counterE++;
            item.idL=counterE;
            theApps2.push(item);
        }
    }

    if ((item!=null)&&(currentInApp!=null)){
        counterI++;
        currentInApp.idL=counterI;
        theApps2.push(currentInApp);
    }
    //invert
    var theApps3=[];
    for (var i = 0, len = theApps2.length; i < len; i++) {
        theApps3.push(theApps2[len-i-1]);
    }
    return theApps3;
};

Let’s say that all the values are stored on the Local-Storage.

Right now it works perfectly but I need to change the sorting criteria but keeping the sort by date. I mean, adding an option selector which allows you to choose to which parent a child will be assigned. I know it can be solved using something like the parent id or the parent name, or both, im a wa that the selector show you the parent “cname” for you to choose from he list. On the html part it would be something like this:

<li>
<div class="item-content">
    <div class="item-inner">
        <div class="item-input">
            <label class="hidden" for="pid">Select a parent</label>
            <select name="pid" id="pid">
                <option class="item-inner" value="">Select a parent</option>
                <option class="item-inner" value="parent_id">Parent Name</option>
                <option class="item-inner" value="parent_id">Parent Name</option>
                <option class="item-inner" value="parent_id">Parent Name</option>
                
                ..............................
                
                <option class="item-inner" value="parent_id">Parent Name</option>
            </select>
        </div>
    </div>
</div>
</li>

but I am stucked on the js part.

How to modify the above js code to show in the form a list of all the previosly created parents to choose from in order to assign a child?

Something like this:

the desired result

How can I make the ddChild dropdown conditionally required and its selected value should not be the initial value(which is value=””)

How can I make the ddChild dropdown conditionally required and its selected value should not be the initial value(which is value=””), but only if the ddParent dropdown’s selected value is 3, using the jQuery Validation Plugin.

<form id="myForm">
    <select name="ddParent" id="ddParent">
        <option value="">Please select</option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
    </select>
    <select name="ddChild" id="ddChild">
        <option value="">Please select</option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
    </select>    
</form>

Replicating a web based interactive page locally to process bulk operations

So here is the project I am working on and the issues I need to address, Ill appreciate your input, for now it is more of an “software design” that will turn into coding:

There is a website that offers a service (there are thousands like this) where you can input a string of numbers in a window (Java based) by pasting, then you press a button that triggers a process, and the website performs some mathematical operation and prints out an answer under the window. This needs you to paste your inquiring string into the window manually.

So I saved the whole of the website locally and inspected how it works:

That input window and the process button, execute some functions that are in Java files to give the answer.

what I need:

I’d like to pass to this window, thousands of strings of alphanumeric (123n1lkn2l54234n) and capture the outputs,printed out to a file where I can further work with them.

I can see 2 or 3 options to do this:

1- [The harder option]
write a python script that “interacts” with the Java files directly (locally) to use the mathematical functions in them, and then print the output to file. These Java files are enormous with hundreds of function interacting all over the place, I’d have to spend lots of time just to understand every single file…..

2- [The simpler, preferred option]

Use something like Beautiful Soup, to PUSH into the live online website my long list of string+numbers and somehow capture the output?

3- [The “other” simpler, preferred option]

To write a python script that does the same as above, push data into the locally saved website, and captures output to a file. Here I am not sure where my local python script calls the Java file, thorough the HTML window.

How would you recommend approaching this challenge?

Thank you!

How can I login to 4th party API using my credentials + generating a JWT?

I’m trying to log in to a 4th party website’s API using a POST request and javascript. Normally this would be easy if I created the API, or worked directly with the creator, but neither is the case here. To explain why: I want to use my login to access some private endpoints that I would normally be able to access on a website in the browser.

The problem is that the login endpoint requires a token, which I’m assuming is a JWT, when inspecting the network while logging in.

/login payload:

{
    "email": "*@*.com",
    "password": "********",
    "token": "03AFcWeA7lNwKR5KfUA7CsHb-LPduxc_R5ondn4RmMHgmmNagBeoVxo5U2ILNB5fRrNIsAPcuRVj1Dk76ZDjg9YTmxHqrvsY5uDO7KxwENwJEJvwur2ciHo_-AAxoqvz2D52sm8vDgza3sN2myzUjP4xjRQVsRJ7Nx3IRx4v5p1PcDJNsxoGhZOiEU1Wg1kHO0uhth48zd7Y7z8xZtgIgHpb9JkE2BPbXx06D8FA4BYjhujehEsnx2okF9RamM7NBlewGNinJ2EiGZh7mMk3e4uiFJ3hao_fuj0ekrHs4h1UGiAk02UbxJqLnPEqpOUiIjzfgAbM4Mvw_IPympEQCqihFPH4w_F8Aln-tHkVxS5wHWYBfxgGC4k-bXI2geSOKclYOhEnk_El_1AKROgefTBoOnQrVLKgPCRsKs6E25Izc01Y_8EAgbb6RR40woBkZDwfdliRTY0hnY8DfCsrZDT8JX6HOA4e8Dm3ArITuiSlZb_q6Y_JfMTS8Hf5awXTk8MghoISNX1oXSwuGgkLnU92-23fRXrrG74yhPTtgrylRnRTIv8eJ2BhcmNYMHVP9Q4GW77Rj8kdD6BWxlB_JetOLsGGsDeawUdwzhTwVOSwWLCzcZzyPf6BfVrcEaXUqPH83rrQ4XaGLkOIEeyMvIj4G7oKvxEv7bU8Ad7FGuGv3hizYH1Naeqg_hF7YOVitWSbJ1CDdQToxjA4i9zq1VQXwE0Bcv0Lk8wLXIz5TR6cmgh0BpIpRltDBrTerA0T9axvyJNnPMWlsHE2a-SgGnIeotAb0-qp8vN6utBu-1aH-7s5shpxP8mDgMQihHVyn1Aapb3uRURem9y9RHUPHw32RzjKR_DGaLg1oz2ApFiwBWRCu0AL-iNOErQPIUsOfKhBH57m-LLv-8D4KbeUzhVgdZE3mfL_YX6Ad1oWkHCkvRknTwpzTJNrPF_Na7yh2wFjcqVS_bS3hVTl2D9T9MLj6WO3ZN6XmV5g1t8ocW3wyQTxUdUDvqgH7K19TRH7ZsMIxsgl-PRC4NKs1a3fXyAKvMdssjBV30-LIQ2dWhl9ZNMChD5Np6uWsNmw-tAZPdJhfbGUUEfszR8lgvKxCA-DcXTJKL1AUoBpMriM3kdVUann9UaVLZtGJiGukajKqpnUHTENI9ZOwf0fmyuEtXXElZyLRoMOiz7BkQDzDNWpHpSmn0wGEqEc888uFo2IO1_hK-1RdghGNUhKVOjGqAv5O4QHbOrdYAqRVHqgMvWiQV9U62og2GxXgay5w-ZX4ldLeshqo-g3HD0IDXfjLaEPhFh1uEyOpDsgC2oRdpF_b4rr4ECz7poqxh8VZTw97RyeJPwizEa50VZVNKpUBuOl-IgpnFPCVmUZYGpsh8zJsTrL2KQYS6KFPMA930g0OaDmWnVT0J035p8Y6S86s16HT2Sp0vwrFzq5LRGje0I6_9QJ_Wz131PWEIptoi-xf6VJVEmyxkTu9JUA04CHyjKL4e84RLiEBFH15QJDcHupREYZMsbJhQByrtCh7yHhAzKW2szx2ICpNAy5O38z--TQ4pYiMWhxs9XP9YIVA2IzHUhpWkCymF1JrYn4VGHqrbqltQZOFJsiphB_G0i3BDh9eicw0UHSxqGVRIze1C-u-FnSlTzdH9h2qZrWuDXsaZN9F80FA_yobH46DOfQvJ5ELpeGiUu2Lm1KxEI5_KlxgVYlxm73o9kJMM3SL57CUHvxsKYy1x5E73QJT9DcHfa_hXZ6OO2FjvVJVqcyQi3_OyFVcp2jBA05_lbv1anxnskhDfa-mUlUkCrxBL6hMjKKUQLe_B73p3jXXxqV8nkvarHuDmuHPvSs4iDnnabtIOcqfKCelE19eE_SBea-Ra8csWebqcR7O8COIWxh4QcFOskDlU9r5hhL3bDyVrPCP4HbseWTevqUfhe-1s5btjHCPocSakrnCNbj1gPtyiPbnuvrlYKBG6Z6n625GBQLlyoQDdHPZVYa9mNfR7dH3mILYREGboqbQFOFLc2sfdZ3PwCduAruU0AVk"
}

Paying attention to the network inspector further, I see a REST request done every 30 seconds to the endpoint /validate.

/validate response (the response immediately preceding logging in):

{
    "h": "b6c7119b7e59224b",
    "m": 10,
    "n": 4000,
    "validation_id": "1d9797c2-4c7d-436f-9d75-407c570257f7"
}

Observations of /validate/:

"h" and ‘”validation_id”` are different in every response.

"m": 10 is always the same before and after login.

"n": 4000 is consistently the same before login.

"n": 500 is consistently the same after login.

I suspect the above is used to create the JWT, but I have no idea how to do it or how to find what method of encoding to use.

I’m using node.js request to do the request, but again I don’t have the token generated.

var request = require('request');
var clientServerOptions = {
    url: 'https://*.com/login',
    body: JSON.stringify({
        email: '*@*.com',
        password: '********',
        token: '????????'
    }),
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    }
};

Hiding Script on Mobile

I am using widgetbot on my forum, but the icon covers up important information on mobile. Is there a way to hide this only on mobile? The script has been added into the header via admin panel.

I have tried using CSS and the below codes.

Also, something to note: I am using Flarum forum software and do not have a viable way to edit root files without the edit being replaced in the updates.

Original:

<script src='https://cdn.jsdelivr.net/npm/@widgetbot/crate@3' async defer>
    new Crate({
        server: 'XXXXXXXXXXXXXXXXXXX', // DISCORD
        channel: 'XXXXXXXXXXXXXXX' // ⁠general
    })
 button.notify({
      content: 'Background updated',
      timeout: 1000
    })


</script>

Updated (didn’t work):

<script src='https://cdn.jsdelivr.net/npm/@widgetbot/crate@3' async defer>
function includeHTML() {
  if (mobilecheck()) {
      return;
  }
    new Crate({
        server: 'XXXXXXXXXXXXXXXXXXX', // DISCORD
        channel: 'XXXXXXXXXXXXXXX' // ⁠general
    })
 button.notify({
      content: 'Background updated',
      timeout: 1000
    })
</script>