Did not execute own validation in JS

I want to redesign the default validation in HTML5. I do this with help https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation (example begins Now let’s look at the JavaScript that implements the custom error validation.)

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous" asp-append-version="true">
    <script src="../src/script.js"></script>
  </head>
  <body>

  <form asp-controller="Cards" asp-action="Create" method="post" class="cards" id="deckForm">
            <div class="card mt-6">
                <div class="header d-flex justify-content-between p-3">
                    <h4 class="card-counter">1</h4>
                    
                    <a class="button-bin btn" id="firstCard" ></a>

                </div>

                <div class="card-body row">
                    <div class="term col">
                        <h3>Term</h3>
                        <input class="form-control w-100" name="term" required>
                        <span class = "error"></span>
                    </div>
                    <div class="definition col">
                        <h3>Definition</h3>
                        <input class="form-control w-100" name="definition" required>
                        <span class = "error"></span>

                    </div>
                </div>
            </div>

            <button type="submit" id="create-cards" class="btn btn-primary mt-2">Create</button>
        </form>

        <button class="new-card w-100 d-flex justify-content-center align-items-center mt-4 mt-s rounded-2" style="height: 5rem" type="button">
            <h3>+ Add card</h3>
        </button>

  </body>
</html>

JS

let currentCardNumber = 1;
function addCard() {
  currentCardNumber++;

  let newCardHTML = `
                    <div class="header d-flex justify-content-between p-3">
                        <h4 class="card-counter">${currentCardNumber}</h4>
                        <a class="button-bin btn"  id = "bin${currentCardNumber}"></a>
                    </div>
                    <div class="card-body row">
                        <div class="term col">
                            <h3>Term</h3>
                            <input class="form-control w-100" name = "term"  required>
                        </div>
                        <div class="definition col">
                            <h3>Definition</h3>
                            <input class="form-control w-100" name="definition" required>
                        </div>
                    </div>
            </div> `;
  let newCard = document.createElement('div');
  newCard.classList.add('card');
  newCard.classList.add('mt-3');
  newCard.innerHTML = newCardHTML;

  let addNewCard = document.querySelector('.cards');
  let referenceNode = document.getElementById('create-cards');
  addNewCard.insertBefore(newCard, referenceNode);
  saveCardsHTML();
}

const errorTerm = document.querySelector('.term  .error');
function showError(element) {
  if (element.validity.valueMissing) {

    errorTerm.textContent = 'You need to enter an e-mail address.';
  }
  errorTerm.className = "error active";
}


document.addEventListener('DOMContentLoaded', function () {
  "use strict";
 
  let newCard = document.querySelector('.new-card');
  newCard.addEventListener('click', function () {
    addCard();
  });

  const term = document.querySelector('input[name="term"]');
  term.addEventListener("input", function (event) {

    if (term.validity.valid) {
      errorTerm.textContent = ""; 
      errorTerm.className = "error"; 
    } else {
      showError();
    }
  });


  let deckForm =document.getElementById('deckForm');
  deckForm.addEventListener('submit', function (event) {
    event.preventDefault();
    if(!term.validity.valid){
      showError(term);
      event.preventDefault();
    }
    else{
      saveCardDataToServer();
    }
  });
  
    
});

If I want to move this code from document.addEventListener('DOMContentLoaded', function ()

const term = document.querySelector('input[name="term"]');
  term.addEventListener("input", function (event) {

    if (term.validity.valid) {
      errorTerm.textContent = ""; 
      errorTerm.className = "error"; 
    } else {
      showError();
    }
  });


  let deckForm =document.getElementById('deckForm');
  deckForm.addEventListener('submit', function (event) {
    event.preventDefault();
    if(!term.validity.valid){
      showError(term);
      event.preventDefault();
    }
    else{
      saveCardDataToServer();
    }
  });

I can’t add card. If I return the code, cards add.

event.StopPropogation not working in react

I am having some weird issue which I want to know why that is happening.
I am using MUI and React. Here if I click on my menu icon (which opens the menu) even if I add the stopPropogation. It still fire’s my top most paper element onClick handler. Tried the preventDefault too but the immediate parents (Box & Stack element) onClick is not getting triggered. It’s kind of jumping directly to parent.

Code

// react
import { useState } from "react";
// mui
import {
  Paper,
  Card,
  CardContent,
  Typography,
  CardActions,
  Menu,
  MenuItem,
  Skeleton,
  Stack,
  Box,
  IconButton,
} from "@mui/material";
import DeleteForeverIcon from "@mui/icons-material/DeleteForever";
// components
import Chip from "../base/chip";
import { Button } from "../base";
import { ProjectInfo } from "@/utils/types";
import { format } from "date-fns";
import { MoreHoriz } from "@mui/icons-material";

function ProjectMenu({
  anchorEl,
  open,
  handleClose,
  handleOpenDeleteModal,
  // handleOpenEditModal,
  projectId,
}: {
  anchorEl: Element | null;
  projectId: string | number;
  open: boolean;
  handleClose: () => void;
  handleOpenDeleteModal: (projectId: string | number) => void;
  // handleOpenEditModal: (projectId: string | number) => void;
}) {
  const menuOptions = [
    {
      title: "Delete Vault",
      handler: (projectId: string | number) => {
        handleOpenDeleteModal(projectId);
        handleClose();
      },
      icon: (
        <DeleteForeverIcon sx={{ mr: 2, color: "customColors.error.main" }} />
      ),
      sx: { color: "customColors.error.main" },
    },
  ];

  return (
    <Menu
      anchorEl={anchorEl}
      open={open}
      onClose={handleClose}
      anchorOrigin={{
        vertical: "top",
        horizontal: "left",
      }}
      transformOrigin={{
        vertical: "top",
        horizontal: "left",
      }}
      slotProps={{
        paper: {
          sx: {
            borderRadius: 2,
          },
        },
      }}
    >
      {menuOptions.map((option, index) => (
        <MenuItem
          key={`option-${index}`}
          onClick={(e) => {
            e.stopPropagation();
            option.handler(projectId);
          }}
          sx={{
            fontSize: 14,
            fontWeight: "normal",
            lineHeight: "1.25rem",
            borderBottom: "1px solid #F2F4F7",
            ":last-child": {
              borderBottom: "1px solid transparent",
            },
            ...option.sx,
          }}
        >
          {option.icon} {option.title}
        </MenuItem>
      ))}
    </Menu>
  );
}

export default function ProjectCard({
  projectInfo,
  disableMenu,
  handleDelete,
  handleEdit,
  handleView,
  onClick,
}: {
  projectInfo: ProjectInfo;
  disableMenu?: boolean;
  onClick: () => void;
  handleDelete: (projectId: string | number) => void;
  handleEdit: (projectId: string | number) => void;
  handleView: (projectId: string | number) => void;
}) {
  const [anchorEl, setAnchorEl] = useState<null | Element>(null);
  const open = Boolean(anchorEl);
  return (
    <Paper
      elevation={0}
      sx={{
        boxShadow: "0px 2px 20px 0px rgba(0, 0, 0, 0.08)",
        borderRadius: 2.5,
        bgcolor: "background.paper",
        cursor: "pointer",
        transition: "transform .2s ease-in, border-color .2s ease-in",
        border: "2px solid transparent",
        ":hover": {
          transform: "scale(1.01)",
          border: "2px solid",
          borderColor: "customColors.primary.main",
        },
        display: "flex",
        flexDirection: "column",
        justifyContent: "space-between",
        flex: 1,
        height: "100%",
      }}
      onClick={() => {
        alert("bubblepaper");
      }}
    >
      <Stack
        sx={{
          p: 3,
          display: "flex",
          flexDirection: "column",
          justifyContent: "space-between",
          position: "relative",
          height: "100%",
        }}
        onClick={(e) => {
          e.stopPropagation();
          e.preventDefault();
          alert("bubblestack");
        }}
      >
        <Box
          onClick={(e) => {
            // setAnchorEl(e.currentTarget);
            e.stopPropagation();
            e.preventDefault();
            alert("bubblebox");
          }}
          sx={{
            position: "absolute",
            top: 5,
            right: 5,
            border: "1px solid red",
          }}
        >
          {!disableMenu && (
            <IconButton
              onClick={(e) => {
                e.stopPropagation();
                setAnchorEl(e.currentTarget);
              }}
            >
              <MoreHoriz />
            </IconButton>
          )}
        </Box>
        <Stack>
          <Typography
            sx={{
              fontSize: 22,
              fontWeight: 500,
              lineHeight: "normal",
              letterSpacing: "-0.32px",
              color: "customColors.text.greyBlack",
              whiteSpace: "nowrap",
              textOverflow: "ellipsis",
              width: "calc(100% - 30px)",
              overflow: "hidden",
              mr: 1,
            }}
          >
            {projectInfo?.name
              ? projectInfo?.name?.charAt(0)?.toUpperCase() +
                projectInfo?.name?.slice(1)
              : "-"}
          </Typography>
          <Typography
            mb={0.5}
            sx={{
              fontSize: 17,
              fontWeight: 600,
              lineHeight: "1.75rem",
              letterSpacing: "-0.25px",
              color: "customColors.text.greyBlack",
              whiteSpace: "nowrap",
              textOverflow: "ellipsis",
              width: "calc(100% - 30px)",
              overflow: "hidden",
            }}
          >
            {projectInfo?.metadata?.client_name
              ? projectInfo?.metadata?.client_name?.charAt(0)?.toUpperCase() +
                projectInfo?.metadata?.client_name?.slice(1)
              : "-"}
          </Typography>
          <Typography
            mb={2}
            sx={{ color: "customColors.text.grey2", flex: 1 }}
            className="clip-multiline-text2"
          >
            {projectInfo?.description
              ? projectInfo?.description?.charAt(0)?.toUpperCase() +
                projectInfo?.description?.slice(1)
              : "-"}
          </Typography>
        </Stack>

        <Stack gap={2}>
          <Stack>
            <Stack direction="row" alignItems="center" gap={1}>
              <Typography
                sx={{ color: "customColors.text.grey2", mb: 0.5 }}
                component="span"
              >
                Status:{" "}
              </Typography>{" "}
              <Chip
                label="Public"
                size="small"
                sx={{
                  bgcolor: "customColors.error.bg",
                  color: "customColors.error.main",
                  fontWeight: "bold",
                  borderRadius: "3px",
                }}
                iconColor="customColors.error.main"
              />
            </Stack>
            <Typography sx={{ color: "customColors.text.grey2", mt: 0.5 }}>
              Last updated:{" "}
              {projectInfo?.created_at
                ? format(projectInfo?.created_at, "dd/MM/yyyy")
                : ""}
            </Typography>
          </Stack>
          <Stack direction="row" gap={2}>
            <Button
              variant="outlined"
              onClick={() => {
                handleEdit(projectInfo.id);
              }}
            >
              Edit{" "}
            </Button>
            <Button
              variant="contained"
              onClick={() => {
                handleView(projectInfo.id);
              }}
            >
              View{" "}
            </Button>
          </Stack>
        </Stack>
      </Stack>

      <ProjectMenu
        anchorEl={anchorEl}
        open={open}
        projectId={projectInfo?.id}
        handleClose={() => setAnchorEl(null)}
        handleOpenDeleteModal={(projectId) => handleDelete(projectId)}
        // handleOpenEditModal={(projectId) => handleEdit(projectId)}
      />
    </Paper>
  );
}

export function ProjectCardSkeleton() {
  return (
    <Card
      elevation={0}
      sx={{
        boxShadow: "0px 2px 20px 0px rgba(0, 0, 0, 0.08)",
        borderRadius: 2.5,
        bgcolor: "background.paper",
        cursor: "pointer",
        transition: "transform .2s ease-in, border-color .2s ease-in",
        border: "2px solid transparent",
        ":hover": {
          transform: "scale(1.01)",
          border: "2px solid",
          borderColor: "customColors.primary.main",
        },
      }}
    >
      <CardContent sx={{ p: 3, pb: 0 }}>
        <Skeleton
          variant="rounded"
          width="70%
        "
        />
        <Skeleton variant="rounded" width="55%" sx={{ mt: 1 }} />
        <Skeleton variant="rounded" width="100%" height={50} sx={{ mt: 2 }} />
        <Stack direction="row" alignItems="center" gap={2}>
          <Skeleton width="20%" height={30} />
          <Skeleton width="30%" height={30} />
        </Stack>

        <Skeleton width="70%" height={30} />
      </CardContent>
      <CardActions sx={{ px: 3, pb: 4 }}>
        <Skeleton width="20%" height={50} />
        <Skeleton width="20%" height={50} />
      </CardActions>
    </Card>
  );
}


I already tried using stopPropogation and preventDefaults on immidiate parents.

Exploring Game Development with C++ and Embedded TypeScript for Backend – Any Existing Examples? [closed]

I’m currently in the early stages of researching a game development project, and I’m considering using C++ as the primary backend language, while embedding TypeScript (or JavaScript) for some light business logic.

The idea is:

  1. To use C++ for handling high-performance tasks such as network communication, database connections, and complex computations.

  2. To embed TypeScript for writing light logic and hot-reloadable modules, allowing for faster iteration and development.

Are there any existing games or projects that use a similar tech stack?

Iterating over a nested array of objects to create a new object

I have a nested array of objects that looks something like this:

[
 [
  {
   name: 'name',
   prettyFormat: 'joe bloggs'
   uselessInfo: 'drjfghsdr'
  },
  {
   name: 'email',
   answer: '[email protected]',
   uselessInfo: 'liodrgjiwe'
  }
 ]
 [
  {
   name: 'name',
   prettyFormat: 'mark obrien',
   uselessInfo: 'drjfghsdr'
  },
  {
   name: 'email',
   answer: 'mark [email protected]',
   uselessInfo: 'liodrgjiwe'
  }
 ]
]

I need to transform this array into something more sensible, actually a JSON object, with the following format:

{
  "LIST": [
    {
      "name": "joe bloggs",
      "email": "[email protected]",
    },
    {
      "name": "mark o'brien",
      "email": "mark [email protected]",

    },
  ]
}

This is my solution:

  let outputBuilder = []

  staffSubmissionsArray.forEach(subArray => {
    let personObj = {}
    subArray.forEach(obj => {
      if (obj.name == 'name') {
        personObj['name'] = obj.prettyFormat
      } if (obj.name == 'email') {
        personObj['email'] = obj.answer
      } 
      outputBuilder.push(personObj)
    })
  })

  console.log(JSON.stringify({ "LIST" : outputBuilder })

This gets everything into the right format, however, each person is getting duplicated, presumably each time I iterate over each object, but I don’t know how to fix this. Do I need to approach this in a different way?

API request return cors-policy error (here maps)

I need to access the here maps API in order to query the geocode service, which given a text string returns me coordinates. I ran the procedure on the HERE portal created my app and got the codes to make my API call, testing with postman the query is successful and I get the desired response. When I move the logic to visual studio, and run a ketch call to the endpoint in question I get the error cors policy back.

The error occurs on both the development tunnel and localhost:
enter image description here
ERROR

Below is my fetch request to the server:
fetch from server

On the official documentation it is mentioned that the API here has the Access-control-allow-origin at * so I expect not to have to handle anything else code side… if I am wrong I speak from inexperience it is the first time I am confronted with this error…

documentazione here maps

Does anyone know how I can fix this error? Thanks in advance..

I’m trying to filter an array to print read book using express but it can not be read or empty result

I have a booklist and try to print out those already read in ‘title by author’ form

const bookList = [
    {title: "Harry Potter", author: "J.K. Rowling", alreadyRead: true},
    {title: "Never Eat Alone", author: "Keith Ferrazzi", alreadyRead: false},
    {title: "INSPIRED", author: "Marty Cagan", alreadyRead: false},
    {title: "Zero to One", author: "Peter Thiel", alreadyRead: true}
]

at first I use this for loop method by passing the booklist and status to call the function printBookList(bookList, true) but it end up printing all the elements in the list

function printBookList(bookList, completedReadingBook){
    for(i=0;i<bookList.length;i++){
        if (bookList[i].alreadyRead == completedReadingBook) {
            console.log(bookList[i].title + ' by ' + bookList[i].author);
        }
    }  
}

then I also try with filter() method as below but it end up showing empty

for(i=0; i<bookList.length;i++){
    let filtered = bookList.filter((readbook)=>readbook.alreadyRead==completedReadingBook)
    return filtered;
    }
    console.log(bookList[filtered].title + ' by ' + bookList[filtered].author);

I’m quite new to this js, will be much appreciate if someone could explain this to me, thx a lot!

How to build a music app in Next.js: which dependencies should I use? [closed]

I’m planning to build a music app using Next.js, and I’m curious about the best dependencies and libraries to use for this project. Could you share your recommendations based on your experience? Specifically, I’m looking for suggestions for handling audio playback, user authentication, and database integration. If you’ve worked on a similar project, what were the key dependencies you found helpful? Any advice or insights would be greatly appreciated!

So far, I haven’t started the project yet, but I’ve done some research on potential tools and libraries that could be useful for building a music app in Next.js. I’ve looked into various audio players, authentication options, and database solutions, but I want to gather more input before finalizing my stack.

How to properly animate loading bar in React?

I’m building a loading bar in React, but something is not right. I want it to fill width 100% once the timer is reached 3 seconds, but for some reason it does not work as expected.

const { useState, useEffect } = React;

const Loading = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [progress, setProgress] = useState(0);

  useEffect(() => {
    const duration = 3000;
    const increment = 100 / duration;

    const timer = setInterval(() => {
      setProgress((prevProgress) => {
        const newProgress = prevProgress + increment;
        if (newProgress >= 100) {
          clearInterval(timer);
          setIsLoading(false);
          return 100;
        }
        return newProgress;
      });
    }, 10);

    return () => clearInterval(timer);
  }, []);

  return (
    <div className="canvas">
      {isLoading && (
        <div
          className="loadng_bar"
          style={{ width: `${progress}%` }}
        ></div>
      )}
    </div>
  );
};

// Render it
ReactDOM.createRoot(
  document.getElementById("root")
).render(
  <Loading />
);
.loadng_bar {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 5px;
  background-color: #c4483f;
  transition: width 3.05s linear;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>

It should increase the progress up to full width during 3 seconds. How can I achieve it?

does nodejs’s eval() would change the behavior of var keyword?

all these code snippets run in nodejs.

below are demo1.js, ps: run these code in nodejs rather than browser js engine

// demo1.js

var1 = 'var1';  // in nodejs or Chrome-V8 js engine, this line would create a property named var1 into globalThis/this/window obj
console.log("[globalThis.var1]:", globalThis.var1);  // var1

globalThis.var2 = 'var2';
console.log('[var2]:', var2);  // var2

var var3 = 'var3';  // in nodejs, this line would not create a property named var3 into globalThis
console.log("[globalThis.var3]:", globalThis.var3);  // undefined

function baz() {
  var var4 = 'var4';  // in nodejs, this line would not create a property named var4 into globalThis
  console.log('[globalThis.var4]:', globalThis.var4);
}
baz();  // undefined

(function () {
  var var5 = 'var5';  // in nodejs, this line would not create a property named var5 into globalThis
  console.log('[globalThis.var5]:', globalThis.var5);
})();

I can understand every thing in demo1.js.

below are demo2.js, ps: run these code in nodejs rather than browser js engine

// demo2.js

(function() {
  (0, eval)("var foo = 123;");  (0, eval)("var foo = 123;");  // indirect call eval,create a property named foo into globalThis, which means create a global scope variable foo.
  (0, function() { console.log('[globalThis.foo]:', globalThis.foo); })();
})();
console.log('[globalThis.foo]:', globalThis.foo);  // 123
console.log('[foo]:', foo);  // 123

In demo2.js, I do konw the comma operator would change the eval execution scope to global scope, and also according to Direct and indirect eval – MDN page:
screenshot from MDN eval

My question is:
demo1.js the function baz code block var var4 = 'var4' or the IIFE code block var var5 = 'var5', in nodejs these two line would NOT create a property into globalThis.
But demo2.js the IIFE code block, var foo = 123, in nodejs this line create a property into globalThis.
In both demo1.js and demo2.js, since variables are declared using the var keyword(like var var4 and var var5 in demo1.js, var foo in demo2.js), why is only the var declaration in demo2.js create a property into globalThis?

Long time for queuing to call API

I am facing issue when add extra headers to the request like 'API-Key': 'xxxxxxxxx' I noticed the request take longer time.

please see the two screenshots from chrome when perform the same request without that extra key in the header.

With the extra header key
enter image description here

without the extra header key
enter image description here

how I can kill that extra waiting time ?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API Calls</title>
    <script>
        async function fetchApi(url, headers) {
            const response = await fetch(url, {
                method: 'GET',
                headers: headers
            });
            const data = await response.json();
            return data;
        }

        async function callApis() {
            const apiCalls = [
               
                {
                    name: 'Random User',
                    url: 'https://randomuser.me/api/',
                    headers: {
                        'accept': 'application/json',
                        'API-Key': 'xxxxxxxxx'
                    }
                },
                
            ];

            const resultsContainer = document.getElementById('results');
            resultsContainer.innerHTML = '';

            for (const api of apiCalls) {
                const startTime = performance.now(); // Start timing
                const data = await fetchApi(api.url, api.headers);
                const endTime = performance.now(); // End timing
                const duration = endTime - startTime; // Calculate duration
                resultsContainer.innerHTML += `<h3>${api.name}</h3><pre>${JSON.stringify(data, null, 2)}</pre><p>Duration: ${duration.toFixed(2)} ms</p>`;
            }
        }

        // Call the APIs when the window loads
        window.onload = callApis;
    </script>
</head>
<body>
    <h1>API Calls Results</h1>
    <div id="results"></div>
</body>
</html>

handleChange is not a function when passing function as a parameter

I have two React components and I want to make them so that selecting something in one of them results in another changing.

const MainTest = () => {
    const [selectedTable, setSelectedTable] = useState("");

    function handleSelectedTableChange(newTable) {
        setSelectedTable(newTable);
    }

    return (

            <div style={{ display: 'flex', flex: 1 }}>
                <div style={{ flex: 1 , background: 'lightgray', border: '5px solid #FFF', borderRadius: '10px', padding: '10px' }}>
                    <DatabaseInfoPanel handleChange={handleSelectedTableChange} />
                </div>
                <div style={{ flex: 3 }}>
                    <DatabaseContent selectedTable={selectedTable} />
                </div>
            </div>
        </div>
    );
}

In DatabaseInfoPanel component:

const DatabaseInfoPanel = (handleChange) => {
   ...

   const handleNodeClick = (event, nodeId) => {

      if (parentDatabase) {
            ...
            handleChange("Test");
        } else {
            ...
        }
   }
}

In DatabaseContent component:

const DatabaseContent = (selectedTable) => {
   ...
   return (
      <div>
         <h1>{selectedTable}</h1>
      </div>
   );
};

However when I select something that will call handleChange function I get:
handleChange is not a function
TypeError: handleChange is not a function
at handleNodeClick (http://localhost:3000/static/js/bundle.js:1418:7)
at handleClick (http://localhost:3000/static/js/bundle.js:67258:25)
at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:89160:18)
at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:89204:20)
at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:89261:35)
at invokeGuardedCallbackAndCatchFirstError (http://localhost:3000/static/js/bundle.js:89275:29)
at executeDispatch (http://localhost:3000/static/js/bundle.js:93418:7)
at processDispatchQueueItemsInOrder (http://localhost:3000/static/js/bundle.js:93444:11)
at processDispatchQueue (http://localhost:3000/static/js/bundle.js:93455:9)
at dispatchEventsForPlugins (http://localhost:3000/static/js/bundle.js:93464:7)

Although I am pretty certain that handleChange is in fact, a funciton.

Error ‘Cannot read properties of undefined (reading ‘pushEvent’)’ in Custom Visualizations Grafana

I get the error Cannot read properties of undefined (reading ‘pushEvent’) when I create custom visualizations, please tell me how to fix it.
screenshot error

I get this error when I use the useBlinkingCells custom hook.

Here is a sample code:

import React from 'react';
import { DataFrame, PanelProps } from '@grafana/data';
import { SimpleOptions } from 'types';
import { useBlinkingCells } from 'hooks'; // custom hook

interface Props extends PanelProps<SimpleOptions> {}

export const TablePanel: React.FC<Props> = (props) => {
    ...
   const { blinkingCells } = useBlinkingCells(
    args
   );

    ...
}
export const useBlinkingCells = (
  props
) => {
  const [blinkingCells, setBlinkingCells] = useState({});
  ...
  return {blinkingCells}
}

When I remove the useBlinkingCells custom hook the error goes away, but I need the hook to work.

Thanks in advance!

AxiosError Request failed with status code 401 – 401 (Unauthorized)

I’m new to Laravel & react
I have a web api using Laravel 11 for the backend and react frontend
the authentication works OK with Postman for

http://localhost:8000/api/v1/login 200OK

http://127.0.0.1:8000/sanctum/csrf-cookie
returns
{
“ok”: true
}

http://127.0.0.1:8000/api/v1/logout as well

All works ok if we use Postman
but if we use react then we have an issue with the LOGOUT only
there is no issue with the Login the issue is only with the Logout
here is my code and the error.

Api.js

import axios from 'axios';

// API URL from the environment for versioned endpoints (e.g., /api/v1)
const API_URL = import.meta.env.VITE_REACT_APP_API_URL;

// CSRF URL from the environment for non-versioned requests
const CSRF_URL = import.meta.env.VITE_REACT_APP_CSRF_URL;

// Create axios instance for versioned API requests (/api/v1)
const api = axios.create({
  baseURL: import.meta.env.VITE_REACT_APP_API_URL,
  headers: {
    'Content-Type': 'application/json',
  },
  withCredentials: true,
});

// Create axios instance for CSRF token requests (without /api/v1 prefix)
const csrfApi = axios.create({
  baseURL: CSRF_URL,
  headers: {
    'Content-Type': 'application/json',
  },
  withCredentials: true, // Ensure cookies are sent with CSRF requests
});

// Log all axios requests and responses for debugging purposes
api.interceptors.request.use(
  (config) => {
    console.log("Step 1: Sending request to API", config.url);
    console.log("Step 2: Request Headers: ", config.headers);
    console.log("Step 3: Cookies (withCredentials enabled):", document.cookie); // Log cookies to ensure they're being sent
    return config;
  },
  (error) => {
    console.error("Step 4: Request error", error);
    return Promise.reject(error);
  }
);

api.interceptors.response.use(
  (response) => {
    console.log("Step 5: API Response Success", response);
    return response;
  },
  (error) => {
    console.error("Step 6: API Response Error", error.response ? error.response.data : error);
    return Promise.reject(error);
  }
);

// Function to get CSRF token from Sanctum
export const getCsrfToken = () => {
  console.log("Step 7: Fetching CSRF token...");
  return csrfApi.get('/sanctum/csrf-cookie')
    .then((response) => {
      console.log("Step 8: CSRF token fetched successfully", response.data);
      console.log("Step 9: Current Cookies after CSRF fetch", document.cookie);  // Ensure the CSRF cookie is present
    })
    .catch((error) => {
      console.error("Step 10: CSRF fetch error", error.response ? error.response.data : error);
    });
};


// Handle the login request
// Handle the login request
export const login = (credentials) => {
  console.log("Logging in with credentials", credentials);
  return getCsrfToken().then(() =>
    api.post('/login', credentials, { withCredentials: true })  // No need to manually handle the token
      .then((response) => {
        console.log("Login successful, response:", response.data);
        return response.data;
      })
      .catch((error) => {
        console.error("Login failed", error.response ? error.response.data : error);
        return Promise.reject(error);
      })
  );
};


export const logout = () => {
  return getCsrfToken().then(() =>
    api.post(import.meta.env.VITE_REACT_APP_LOGOUT_ENDPOINT, {}, {
      withCredentials: true, // This will ensure the HttpOnly cookie is sent with the request
    })
    .then((response) => {
      console.log("Step 15: Logout successful:", response.data);
      return response.data;
    })
    .catch((error) => {
      console.error("Step 16: Logout failed", error.response ? error.response.data : error);
      return Promise.reject(error);
    })
  );
};

// Get the authenticated user
export const getUser = () => {
  console.log("Step 17: Fetching authenticated user data...");
  return api.get('/user')
    .then((response) => {
      console.log("Step 18: User data fetched:", response.data);
      return response.data;
    })
    .catch((error) => {
      console.error("Step 19: Fetch user data failed", error.response ? error.response.data : error);
      return Promise.reject(error);
    });
};

export default api;

AppHeaderDropdown.js

import React, { useState } from 'react';
import {
  CAvatar,
  CBadge,
  CDropdown,
  CDropdownDivider,
  CDropdownHeader,
  CDropdownItem,
  CDropdownMenu,
  CDropdownToggle,
  CSpinner,
} from '@coreui/react-pro';
import { useNavigate } from 'react-router-dom';
import CIcon from '@coreui/icons-react';
import {
  cilBell,
  cilCreditCard,
  cilCommentSquare,
  cilEnvelopeOpen,
  cilFile,
  cilLockLocked,
  cilSettings,
  cilTask,
  cilUser,
  cilAccountLogout,
} from '@coreui/icons';
import avatar8 from './../../assets/images/avatars/8.jpg';
import { logout } from '../../services/api';
import { useTranslation } from 'react-i18next';

const AppHeaderDropdown = () => {
  const navigate = useNavigate();
  const [isLoggingOut, setIsLoggingOut] = useState(false);
  const { t } = useTranslation();

  const handleLogout = async () => {
    setIsLoggingOut(true);
    console.log("Step 20: Logout button clicked");

    try {
      const result = await logout();
      console.log("Step 21: Logout result:", result);
      navigate('/login', { replace: true });
    } catch (error) {
      console.error("Step 22: Logout failed:", error);
    }

    setIsLoggingOut(false);
  };

  if (isLoggingOut) {
    return (
      <div className="d-flex justify-content-center align-items-center min-vh-100">
        <CSpinner color="primary" variant="grow" /> {t('logging_out')}
      </div>
    );
  }

  return (
    <CDropdown variant="nav-item" alignment="end">
      <CDropdownToggle className="py-0" caret={false}>
        <CAvatar src={avatar8} size="md" />
   
          <CBadge color="warning-gradient" className="ms-2">42</CBadge>
        </CDropdownItem>
        <CDropdownHeader className="bg-body-secondary text-body-secondary fw-semibold my-2">
          {t('settings')}
        </CDropdownHeader>
      
        <CDropdownItem onClick={handleLogout}>
          <CIcon icon={cilAccountLogout} className="me-2" />
          {t('logout')}
        </CDropdownItem>
      </CDropdownMenu>
    </CDropdown>
  );
};

export default AppHeaderDropdown;

sanctum.php

return [


    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        Sanctum::currentApplicationUrlWithPort()
    ))),

    'guard' => ['web'],   
    'expiration' => 60, 
    'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),

cors.php

<?php

return [


    'paths' => ['api/*', 'sanctum/csrf-cookie'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['http://localhost:3000'],  // Replace with your frontend URL
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => true,  // This ensures that cookies are allowed
];

AuthController.php

<?php

namespace AppHttpControllers;

use AppModelsUser;
use AppModelsUserProvider;
use IlluminateAuthEventsPasswordReset;
use IlluminateAuthEventsRegistered;
use IlluminateAuthEventsVerified;
use IlluminateHttpJsonResponse;
use IlluminateHttpRedirectResponse;
use IlluminateHttpRequest;
use IlluminateSupportFacadesCrypt;
use IlluminateSupportFacadesHash;
use IlluminateSupportFacadesPassword;
use IlluminateSupportStr;
use IlluminateValidationRules;
use IlluminateValidationValidationException;
use IlluminateViewView;
use LaravelSocialiteFacadesSocialite;

class AuthController extends Controller
{
    /**
     * Register new user
     */
    public function register(Request $request): JsonResponse
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:' . User::class],
            'password' => ['required', 'confirmed', RulesPassword::defaults()],
        ]);

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        $user->ulid = Str::ulid()->toBase32();
        $user->save();

        $user->assignRole('user');

        event(new Registered($user));

        return response()->json([
            'ok' => true,
        ], 201);
    }

    /**
     * Redirect to provider for authentication
     */
    public function redirect(Request $request, string $provider): RedirectResponse
    {
        return Socialite::driver($provider)->stateless()->redirect();
    }

    /**
     * Handle callback from provider
     * @throws Exception
     */
    public function callback(Request $request, string $provider): View
    {
        $oAuthUser = Socialite::driver($provider)->stateless()->user();

        if (!$oAuthUser?->token) {
            return view('oauth', [
                'message' => [
                    'ok' => false,
                    'message' => __('Unable to authenticate with :provider', ['provider' => $provider]),
                ],
            ]);
        }

        $userProvider = UserProvider::select('id', 'user_id')
            ->where('name', $provider)
            ->where('provider_id', $oAuthUser->id)
            ->first();

        if (!$userProvider) {
            if (User::where('email', $oAuthUser->email)->exists()) {
                return view('oauth', [
                    'message' => [
                        'ok' => false,
                        'message' => __('Unable to authenticate with :provider. User with email :email already exists. To connect a new service to your account, you can go to your account settings and go through the process of linking your account.', [
                            'provider' => $provider,
                            'email' => $oAuthUser->email,
                        ]),
                    ],
                ]);
            }

            $user = new User();
            $user->ulid = Str::ulid()->toBase32();
            $user->avatar = $oAuthUser->picture ?? $oAuthUser->avatar_original ?? $oAuthUser->avatar;
            $user->name = $oAuthUser->name;
            $user->email = $oAuthUser->email;
            $user->password = null;
            $user->email_verified_at = now();
            $user->save();

            $user->assignRole('user');

            $user->userProviders()->create([
                'provider_id' => $oAuthUser->id,
                'name' => $provider,
            ]);
        } else {
            $user = $userProvider->user;
        }

        $token = $user->createDeviceToken(
            device: $request->deviceName(),
            ip: $request->ip(),
            remember: true
        );

        return view('oauth', [
            'message' => [
                'ok' => true,
                'provider' => $provider,
                'token' => $token,
            ],
        ]);
    }

    /**
     * Generate sanctum token on successful login
     * @throws ValidationException
     */
    public function login(Request $request): JsonResponse
    {
        $request->validate([
            'email' => ['required', 'string', 'email'],
            'password' => ['required', 'string'],
        ]);

        $user = User::where('email', $request->email)->first();

        if (!$user || !Hash::check($request->password, $user->password)) {
            throw ValidationException::withMessages([
                'email' => __('auth.failed'),
            ]);
        }

        // Create the token
        $token = $user->createToken('auth_token')->plainTextToken;

        // Set the token as HttpOnly cookie
        return response()->json([
            'ok' => true,
        ])->cookie(
                'token', // cookie name
                $token, // token value
                60 * 24 * 7, // cookie expiration time in minutes (1 week)
                '/', // path
                null, // domain (null will set for the current domain)
                true, // secure (only HTTPS)
                true // HttpOnly (not accessible via JavaScript)
            );
    }

    /**
     * Revoke token; only remove token that is used to perform logout (i.e. will not revoke all tokens)
     */
    public function logout(Request $request)
    {
        // Revoke the current user's token (Sanctum)
        try {
            $request->user()->currentAccessToken()->delete();  // Delete the current token
            return response()->json(['ok' => true, 'message' => 'Logged out successfully.']);
        } catch (Exception $e) {
            return response()->json(['ok' => false, 'message' => 'Logout failed.'], 500);
        }
    }

    /**
     * Get authenticated user details
     */
    public function user(Request $request): JsonResponse
    {
        $user = $request->user();

        return response()->json([
            'ok' => true,
            'user' => [
                ...$user->toArray(),
                'must_verify_email' => $user->mustVerifyEmail(),
                'has_password' => (bool) $user->password,
                'roles' => $user->roles()->select('name')->pluck('name'),
                'providers' => $user->userProviders()->select('name')->pluck('name'),
            ],
        ]);
    }

    /**
     * Handle an incoming password reset link request.
     * @throws ValidationException
     */
    public function sendResetPasswordLink(Request $request): JsonResponse
    {
        $request->validate([
            'email' => ['required', 'email'],
        ]);

        // We will send the password reset link to this user. Once we have attempted
        // to send the link, we will examine the response then see the message we
        // need to show to the user. Finally, we'll send out a proper response.
        $status = Password::sendResetLink(
            $request->only('email')
        );

        if ($status !== Password::RESET_LINK_SENT) {
            throw ValidationException::withMessages([
                'email' => [__($status)],
            ]);
        }

        return response()->json([
            'ok' => true,
            'message' => __($status),
        ]);
    }

    /**
     * Handle an incoming new password request.
     * @throws ValidationException
     */
    public function resetPassword(Request $request): JsonResponse
    {
        $request->validate([
            'token' => ['required'],
            'email' => ['required', 'email', 'exists:' . User::class],
            'password' => ['required', 'confirmed', RulesPassword::defaults()],
        ]);

        // Here we will attempt to reset the user's password. If it is successful we
        // will update the password on an actual user model and persist it to the
        // database. Otherwise we will parse the error and return the response.
        $status = Password::reset(
            $request->only('email', 'password', 'password_confirmation', 'token'),
            static function ($user) use ($request) {
                $user->forceFill([
                    'password' => Hash::make($request->password),
                    'remember_token' => Str::random(60),
                ])->save();

                event(new PasswordReset($user));
            }
        );

        if ($status !== Password::PASSWORD_RESET) {
            throw ValidationException::withMessages([
                'email' => [__($status)],
            ]);
        }

        return response()->json([
            'ok' => true,
            'message' => __($status),
        ]);
    }

    /**
     * Mark the authenticated user's email address as verified.
     */
    public function verifyEmail(Request $request, string $ulid, string $hash): JsonResponse
    {
        $user = User::where('ulid', $ulid)->first();

        abort_if(!$user, 404);
        abort_if(!hash_equals(sha1($user->getEmailForVerification()), $hash), 403, __('Invalid verification link'));

        if (!$user->hasVerifiedEmail()) {
            $user->markEmailAsVerified();

            event(new Verified($user));
        }

        return response()->json([
            'ok' => true,
        ]);
    }

    /**
     * Send a new email verification notification.
     */
    public function verificationNotification(Request $request): JsonResponse
    {
        $request->validate([
            'email' => ['required', 'email'],
        ]);

        $user = $request->user() ?: User::where('email', $request->email)->whereNull('email_verified_at')->first();

        abort_if(!$user, 400);

        $user->sendEmailVerificationNotification();

        return response()->json([
            'ok' => true,
            'message' => __('Verification link sent!'),
        ]);
    }

    /**
     * Get authenticated user devices
     */
    public function devices(Request $request): JsonResponse
    {
        $user = $request->user();

        $devices = $user->tokens()
            ->select('id', 'name', 'ip', 'last_used_at')
            ->orderBy('last_used_at', 'DESC')
            ->get();

        $currentToken = $user->currentAccessToken();

        foreach ($devices as $device) {
            $device->hash = Crypt::encryptString($device->id);

            if ($currentToken->id === $device->id) {
                $device->is_current = true;
            }

            unset($device->id);
        }

        return response()->json([
            'ok' => true,
            'devices' => $devices,
        ]);
    }

    /**
     * Revoke token by id
     */
    public function deviceDisconnect(Request $request): JsonResponse
    {
        $request->validate([
            'hash' => 'required',
        ]);

        $user = $request->user();

        $id = (int) Crypt::decryptString($request->hash);

        if (!empty($id)) {
            $user->tokens()->where('id', $id)->delete();
        }

        return response()->json([
            'ok' => true,
        ]);
    }
}

and here is the output

these steps for login

Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtools
api.js:68 Step 11: Logging in with credentials {email: '[email protected]', password: 'password123'}
api.js:54 Step 7: Fetching CSRF token...
api.js:57 Step 8: CSRF token fetched successfully {ok: true}
api.js:58 Step 9: Current Cookies after CSRF fetch 
api.js:30 Step 1: Sending request to API /login
api.js:31 Step 2: Request Headers:  AxiosHeaders {Accept: 'application/json, text/plain, */*', Content-Type: 'application/json'}
api.js:32 Step 3: Cookies (withCredentials enabled): 
csrf-cookie:1 
        
        
       
        
       Third-party cookie will be blocked in future Chrome versions as part of Privacy Sandbox.Understand this warning
2127.0.0.1:8000/api/v1/login:1 
        
        
       
        
       Third-party cookie will be blocked in future Chrome versions as part of Privacy Sandbox.Understand this warning
api.js:43 Step 5: API Response Success {data: {…}, status: 200, statusText: 'OK', headers: AxiosHeaders, config: {…}, …}
api.js:72 Step 12: Login successful, token received: {ok: true}
Login.js:41 Login successful, token: undefined

===========================

and these steps for logout

Step 20: Logout button clicked
api.js:54 Step 7: Fetching CSRF token...
api.js:57 Step 8: CSRF token fetched successfully {ok: true}
api.js:58 Step 9: Current Cookies after CSRF fetch 
api.js:30 Step 1: Sending request to API /logout
api.js:31 Step 2: Request Headers:  AxiosHeaders {Accept: 'application/json, text/plain, */*', Content-Type: 'application/json'}
api.js:32 Step 3: Cookies (withCredentials enabled): 
api.js:108 
        
        
       POST http://127.0.0.1:8000/api/v1/logout 401 (Unauthorized)
dispatchXhrRequest @ axios.js?v=7d171547:1680
xhr @ axios.js?v=7d171547:1560
dispatchRequest @ axios.js?v=7d171547:2035
Promise.then
_request @ axios.js?v=7d171547:2222
request @ axios.js?v=7d171547:2141
httpMethod @ axios.js?v=7d171547:2269
wrap @ axios.js?v=7d171547:8
(anonymous) @ api.js:108
Promise.then
logout @ api.js:107
handleLogout @ AppHeaderDropdown.js:41
callCallback2 @ chunk-VGGCA2L5.js?v=724d8ce0:3674
invokeGuardedCallbackDev @ chunk-VGGCA2L5.js?v=724d8ce0:3699
invokeGuardedCallback @ chunk-VGGCA2L5.js?v=724d8ce0:3733
invokeGuardedCallbackAndCatchFirstError @ chunk-VGGCA2L5.js?v=724d8ce0:3736
executeDispatch @ chunk-VGGCA2L5.js?v=724d8ce0:7014
processDispatchQueueItemsInOrder @ chunk-VGGCA2L5.js?v=724d8ce0:7034
processDispatchQueue @ chunk-VGGCA2L5.js?v=724d8ce0:7043
dispatchEventsForPlugins @ chunk-VGGCA2L5.js?v=724d8ce0:7051
(anonymous) @ chunk-VGGCA2L5.js?v=724d8ce0:7174
batchedUpdates$1 @ chunk-VGGCA2L5.js?v=724d8ce0:18913
batchedUpdates @ chunk-VGGCA2L5.js?v=724d8ce0:3579
dispatchEventForPluginEventSystem @ chunk-VGGCA2L5.js?v=724d8ce0:7173
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ chunk-VGGCA2L5.js?v=724d8ce0:5478
dispatchEvent @ chunk-VGGCA2L5.js?v=724d8ce0:5472
dispatchDiscreteEvent @ chunk-VGGCA2L5.js?v=724d8ce0:5449
Show 22 more frames
Show lessUnderstand this error
api.js:47 Step 6: API Response Error {ok: false, message: 'Unauthenticated.'}
(anonymous) @ api.js:47
Promise.then
_request @ axios.js?v=7d171547:2222
request @ axios.js?v=7d171547:2141
httpMethod @ axios.js?v=7d171547:2269
wrap @ axios.js?v=7d171547:8
(anonymous) @ api.js:108
Promise.then
logout @ api.js:107
handleLogout @ AppHeaderDropdown.js:41
callCallback2 @ chunk-VGGCA2L5.js?v=724d8ce0:3674
invokeGuardedCallbackDev @ chunk-VGGCA2L5.js?v=724d8ce0:3699
invokeGuardedCallback @ chunk-VGGCA2L5.js?v=724d8ce0:3733
invokeGuardedCallbackAndCatchFirstError @ chunk-VGGCA2L5.js?v=724d8ce0:3736
executeDispatch @ chunk-VGGCA2L5.js?v=724d8ce0:7014
processDispatchQueueItemsInOrder @ chunk-VGGCA2L5.js?v=724d8ce0:7034
processDispatchQueue @ chunk-VGGCA2L5.js?v=724d8ce0:7043
dispatchEventsForPlugins @ chunk-VGGCA2L5.js?v=724d8ce0:7051
(anonymous) @ chunk-VGGCA2L5.js?v=724d8ce0:7174
batchedUpdates$1 @ chunk-VGGCA2L5.js?v=724d8ce0:18913
batchedUpdates @ chunk-VGGCA2L5.js?v=724d8ce0:3579
dispatchEventForPluginEventSystem @ chunk-VGGCA2L5.js?v=724d8ce0:7173
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ chunk-VGGCA2L5.js?v=724d8ce0:5478
dispatchEvent @ chunk-VGGCA2L5.js?v=724d8ce0:5472
dispatchDiscreteEvent @ chunk-VGGCA2L5.js?v=724d8ce0:5449
Show 19 more frames
Show lessUnderstand this error
api.js:116 Step 16: Logout failed {ok: false, message: 'Unauthenticated.'}
(anonymous) @ api.js:116
Promise.catch
(anonymous) @ api.js:115
Promise.then
logout @ api.js:107
handleLogout @ AppHeaderDropdown.js:41
callCallback2 @ chunk-VGGCA2L5.js?v=724d8ce0:3674
invokeGuardedCallbackDev @ chunk-VGGCA2L5.js?v=724d8ce0:3699
invokeGuardedCallback @ chunk-VGGCA2L5.js?v=724d8ce0:3733
invokeGuardedCallbackAndCatchFirstError @ chunk-VGGCA2L5.js?v=724d8ce0:3736
executeDispatch @ chunk-VGGCA2L5.js?v=724d8ce0:7014
processDispatchQueueItemsInOrder @ chunk-VGGCA2L5.js?v=724d8ce0:7034
processDispatchQueue @ chunk-VGGCA2L5.js?v=724d8ce0:7043
dispatchEventsForPlugins @ chunk-VGGCA2L5.js?v=724d8ce0:7051
(anonymous) @ chunk-VGGCA2L5.js?v=724d8ce0:7174
batchedUpdates$1 @ chunk-VGGCA2L5.js?v=724d8ce0:18913
batchedUpdates @ chunk-VGGCA2L5.js?v=724d8ce0:3579
dispatchEventForPluginEventSystem @ chunk-VGGCA2L5.js?v=724d8ce0:7173
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ chunk-VGGCA2L5.js?v=724d8ce0:5478
dispatchEvent @ chunk-VGGCA2L5.js?v=724d8ce0:5472
dispatchDiscreteEvent @ chunk-VGGCA2L5.js?v=724d8ce0:5449
Show 15 more frames
Show lessUnderstand this error
AppHeaderDropdown.js:45 Step 22: Logout failed: AxiosError {message: 'Request failed with status code 401', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}
handleLogout @ AppHeaderDropdown.js:45
await in handleLogout
callCallback2 @ chunk-VGGCA2L5.js?v=724d8ce0:3674
invokeGuardedCallbackDev @ chunk-VGGCA2L5.js?v=724d8ce0:3699
invokeGuardedCallback @ chunk-VGGCA2L5.js?v=724d8ce0:3733
invokeGuardedCallbackAndCatchFirstError @ chunk-VGGCA2L5.js?v=724d8ce0:3736
executeDispatch @ chunk-VGGCA2L5.js?v=724d8ce0:7014
processDispatchQueueItemsInOrder @ chunk-VGGCA2L5.js?v=724d8ce0:7034
processDispatchQueue @ chunk-VGGCA2L5.js?v=724d8ce0:7043
dispatchEventsForPlugins @ chunk-VGGCA2L5.js?v=724d8ce0:7051
(anonymous) @ chunk-VGGCA2L5.js?v=724d8ce0:7174
batchedUpdates$1 @ chunk-VGGCA2L5.js?v=724d8ce0:18913
batchedUpdates @ chunk-VGGCA2L5.js?v=724d8ce0:3579
dispatchEventForPluginEventSystem @ chunk-VGGCA2L5.js?v=724d8ce0:7173
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ chunk-VGGCA2L5.js?v=724d8ce0:5478
dispatchEvent @ chunk-VGGCA2L5.js?v=724d8ce0:5472
dispatchDiscreteEvent @ chunk-VGGCA2L5.js?v=724d8ce0:5449
Show 15 more frames
Show lessUnderstand this error

How to make a whatsapp chatbot without using 3rd Party Services

I want to make dynamic whatsapp chatbots based on configuration specified by users and the only resources I have found regarding it are 3rd party services. I know there is an official Whatsapp API present thought which we can programatically send messages however I have no idea how to make a chatbot using it.

I also saw a portion in the API called webhooks through which you can listen to incoming messages sent by user. Is that how we can make a chatbot or is there some other way?

Any kind of guidance on this would be appreciated. Thanks

Is there a way to yield from any of the generators

I have a function

async function* values(input) {
    ...
}

this will yield some values depending on the input.

Now I have a set of inputs, let’s say [1,2,3,4,5], and I want to create another generator function that will use these inputs and call values for each of them.
I want to yield back from the wrapping generator function whenever any of the values call yields.
The function yields the generator sequentially:

function* generateValues() {
     const inputs = [1,2,3,4,5];

     const generators = inputs.map(input => values(input));

     for (const generator of generators) {
          yield await generator.next();
     }
}

but I want to yield as soon as any of the generators yields, and keep yielding till all generators are drained.

I would like to replace the for loop above, with something like:

for await (const value of Generator.any(generators)) {
    yield value;
}

i.e. I’m looking for something like Generator.any which would be similar to Promise.any but without throwing away the remaining generators.