How to get content from quill?

I built quill into my site, set up a database, prescribed JS code and a handler to send data to the database.

Everything works, but the “content” column always remains empty in the database.

Can you help me with this?

Form:

<form method="POST"> 
    <div class="container"> 
        <input type="text" name="heading" class="form-control title" placeholder="Heading" required/> 
    <br> 
    <div class="container-textarea"> 
        <div id="editor"></div> 
        <input type="hidden" name="content" id="content" value=""> 
    </div> 
    <br> 
    <button type="submit" name="upload" value="upload" class="btn btn-primary">Upload</button> 
    </div> 
</form>

Script:

var toolbarOptions = [
    ['bold', 'italic', 'underline', 'strike'], //toggled buttons
    ['blockquote', 'code-block'],

    [{ 'header': 1 }, { 'header': 2 }], //custom button values
    [{ 'list': 'ordered'}, { 'list': 'bullet' }],
    [{ 'indent': '-1'}, { 'indent': '+1' }], //outdent/indent
    [{ 'direction': 'rtl' }], // text direction

    [{ 'size': ['small', false, 'large', 'huge'] }], //custom dropdown
    [{ 'header': [1, 2, 3, 4, 5, 6, false] }],

    [{ 'color': [] }, { 'background': [] }], //dropdown with defaults from theme
    [{ 'font': [] }],
    [{ 'align': [] }],

    ['clean'] //remove formatting button
    ];

var quill = new Quill('#editor', {
    modules: {
    toolbar: toolbarOptions
    },
    theme: 'snow',
    });

var form = document.querySelector('form');
var contentField = document.getElementById('content');


form.addEventListener('submit', function(event) {
    event.preventDefault();
    var contents = quill.getContents();
    contentField.value = contents;
    form.submit();
    });

I’ve tried a lot of things, and getContents(); (seen above), and quill.root.InnerHTML; and other stuff.

web page dropdown animation jittering

so i’m trying to make a dropdown animation for a list, that activates when hovered, and it mostly just works as i want it to. I used GSAP to make it work by first setting the height so only the title can be seen, then on hover increasing the height of the list, and at the same time moving it down exactly the same amount, but no matter how much i try to adjust the values, there’s still jittering, is there a way to do this properly with GSAP, or would i need to use something else?

HTML

 <div class="languages-dropdown hidden">
            <p class="title">Języki programowania</p>
            <div class="language-list">
                <br>
                <a href="subpages/sub-page0.html" class="language">Javascript</a>
                <a href="subpages/sub-page1.html" class="language">B</a>
                <a href="subpages/sub-page2.html" class="language">C</a>
                <a href="subpages/sub-page3.html" class="language">C++</a>
                <a href="subpages/sub-page4.html" class="language">C#</a>
                <a href="subpages/sub-page5.html" class="language">Rust</a>
                <a href="subpages/sub-page6.html" class="language">Java</a>
                <a href="subpages/sub-page7.html" class="language">Python</a>
                <a href="subpages/sub-page8.html" class="language">Golang</a>
                <a href="subpages/sub-page9.html" class="language">PHP</a>
            </div>
        </div>

CSS

.languages-dropdown {
    position: absolute;
    padding: 17px;
    border: none;
    border-radius: 10px;
    background-color: rgb(53, 53, 53);
    height: 375px;
    width: 230px;
}

.title {
    text-align: center;
    font-size: 20px;
}

.language-list {
    margin-left: 60px;
}

.hidden {
    overflow: hidden;
    max-height: 59px;
}

.language {
    display: block;
    text-decoration: none;
    padding: 5px;
    font-size: 17px;
}

Javascript

let languagesDropdown = document.querySelector(".languages-dropdown")
let languageList = document.querySelector(".language-list")

gsap.set(languagesDropdown, {
    y: -250
})

languagesDropdown.addEventListener("mouseenter", () => {
    gsap.to(languagesDropdown, {
        ease: "power1.inOut",
        duration: 0.2,
        y: -92,
        maxHeight: "375px",
    });
});

languagesDropdown.addEventListener("mouseleave", () => {
    gsap.to(languagesDropdown, {
        ease: "power1.inOut",
        duration: 0.2,
        y: -250,
        maxHeight: 59,
    });
});

i tried to adjust how much the list is moved up, but it either has changed height after the animation is finished, or jitters during the animation

Chart JS, strike through external legend when data disabled

For my Chart JS use, I use an external legend via a callback, because some data sets have a lot of labels.

Example of how the external legend is rendered:

            options: {
                legend: { display: false },
                legendCallback: function(chart) {
                    var text = [];
                    text.push('<div class="collapse_container"><div class="collapse_header">Click to show legend</div><div class="collapse_content"><div class="body group"><ul style="list-style: none; padding: 0; margin: 0;">');
                    for (var i=0; i<chart.data.datasets.length; i++)
                    {
                      text.push('<li id="labelLinuxDistributionsCombined' + i + '" onClick="toggleLabels(' + i + ', ChartLinuxDistributionsCombined)" style="cursor:pointer;user-select:none;float: left; padding: 2px; margin: 0 7px 7px 0; line-height: 15px;">');
                      text.push('<div style="float: left; width: 15px; height: 15px; background-color:' + chart.data.datasets[i].borderColor + '">&nbsp;</div>&nbsp;' + chart.data.datasets[i].label);
                      text.push('</li>');
                    }
                    text.push('</ul><button class="chart-toggle" onClick="toggle_all_Labels(ChartLinuxDistributionsCombined)">show/hide all</button></div></div></div>');
                    return text.join("");
                  },

This allows people to hide the legend too in a collapsable div.

Now I also have this code, that allows people to click on a legend item label to disable/enable the data set on the chart:

function toggleLabels(index,chart)
{
    var ci = chart; //Chart
    var meta = ci.getDatasetMeta(index);
    
    meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;
    
    // We hid a dataset, rerender the chart
    ci.update();
}

This all works great! However…

Is there a way I can adjust that, so when clicked/unlicked the label text has a strikethrough?

How do I render markdown to HTML in real time as the user is typing?

I’m trying to build an input where as you type in Markdown, it gets converted to HTML in real time within the same input.

A real world example of this is Notion. In Notion, if you were to type ‘##’ and then press space, it converts it to an H2 and removes the ‘##’ from the input, and for the user this is seamless, it works really well.

I initially had this logic split. I had a CodeMirror input where you could type your Markdown, and then a div which uses marked to render the markdown. But after looking at Notion, it’s a much smoother experience and I’m curious how they might have implemented something like that.

How can I access the WASM memory of an externally loaded page through a C++ Node Module in Electron

As the title suggests, I am trying to access the WebAssembly (WASM) memory of an externally loaded page (via loadUrl()) from Electron using a C++ Node Module, specifically for read/write operations.

I’m unsure whether to use v8, NAPI, or Nan for this purpose, and I’m uncertain about the process involved.

I had attempted to access it through Electron’s preload, and additionally, I tried performing an AOB scan in the browser process within the C++ module.

Is this workflow safe for authentication?

I have implemented a multistep sign-in workflow, but I am uncertain about its security. I would greatly appreciate it if you could identify any security vulnerabilities in this workflow and provide suggestions to enhance its security.

What I aim to implement?

I want to ensure that a user who enters their email and password but has not set a username cannot sign in. Instead, they should be redirected to a page to set a username. After setting the username, they can log in again without re-entering their credentials, ensuring a one-time input of correct credentials.

Limitations:

I prefer not to collect the username during the signup process. Handling the username should occur after the user verifies their email in signup process.

Implemented Workflow:

I use next-auth for authentication. When a user attempts to log in, first verifies the email and password. If it is correct, it checks whether the user has set a username or not. If the credentials are correct but no username is set, the sign-in fails. However, a JWT token is created for that user in the database, and the signed token is stored in a cookie(http_only,secure). The user is then redirected to another page to set a username. After successfully entering a username, authenticatie user with uses the signed token from the cookie to identify the user without requiring email and password input again just with checking user has any token in database and it match with the signed token in cookie or not? Once the user signs in, the token is deleted from the database.

Cloudflare Bot Protection with subdomains

I own a domain, example.com, which houses a website, and a subdomain, search.example.com, where a search server is installed.

Visitors interact with the website (created with Vue) and multiple client-initiated calls are made to the search server on the search.example.com subdomain.

On this site, the Managed Challenge is enabled. As part of a business subscription, I’ve installed this safeguard because the site is frequently targeted by web scrapers/bots, thus necessitating multiple rules for the activation of a Cloudflare captcha or JavaScript challenge.

I’ve run into an issue where, if a client connects using a “bad ip” source and successfully completes the captcha on the primary domain, this action doesn’t carry over to the search server. Consequently, the main website loads, but the subdomain with the search API does not.

Both the main website and the search server are proxied through Cloudflare. They share the same root domain and reside under the same business account.

What’s the ideal solution for this problem? Or might there be a setting I overlooked that enables the captcha cookie to be shared across both sites?

I’m able to proxy the search engine on a subfolder of the primary domain if nothing else works , but I prefer to have 2 different endpoints that is easier to manage and eventually scale up.

Keep getting “You need to enable JavaScript to run this app.” error after doing production build of react application in api server

I am trying to production build of my react application and host it from my api server. For this, the modifications I made in my client and server side of the applications are listed below –

Client :

enter image description here

package.json

Server :

enter image description here

program.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace API.Controllers
{
    [AllowAnonymous]
    public class FallbackController : Controller
    {
        public IActionResult Index() {
            return PhysicalFile(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "index.html"), "text/HTML");
        }
    }
}

FallbackController.cs

Now, after I started the api server which is in http://localhost:5206/ the application started. But any other functionalities (api calls) are not working.

I am keep getting this message –
enter image description here
enter image description here

The response is –

<html lang="en">
    <head>
        <meta charset="utf-8"/>
        <link rel="icon" href="./favicon.ico"/>
        <meta name="viewport" content="width=device-width,initial-scale=1"/>
        <meta name="theme-color" content="#000000"/>
        <meta name="description" content="Web site created using create-react-app"/>
        <link rel="apple-touch-icon" href="./logo192.png"/>
        <link rel="manifest" href="./manifest.json"/>
        <title>React App</title>
        <script defer="defer" src="./static/js/main.dbac018f.js"></script>
        <link href="./static/css/main.a447ad15.css" rel="stylesheet">
    </head>
    <body>
        <noscript>You need to enable JavaScript to run this app.</noscript>
        <div id="root"></div>
    </body>
</html>

I have tried like every possible solutions and checked different browsers and rebuild the program again and again yet can’t solved this issue. Any suggestions would be helpful, Thanks.

Angular-17 for e-commerce application

I am creating an e-commerce application using angular-17 and I am new to angular. Can any one please help me to create admin dashboard and add-products through dashboard? Below are my files:

product folder–>showcompo+addtocartcompo+productdetailscompo
also productfolder have adminfolder
productfolder–>admin–>addproduct+admindashboard+updateproduct

Question about using Express for redirects

Trying to figure out how to use redirects for SEO purposes, can anyone help? I searched articles online and tried them but says configured incorrectly.

Wanted to get the clear understanding on how to make the redirect work for SEO, image attached on what needs to be done.

How i can add more field when create payment with connect account stripe

I have a question about stripe’s connect account. How i can add more field (etc name, email,..) when create payment
I try to add field defaultValues > billingDetails > name,email,..

[Here is document:]
(https://stripe.com/docs/js/elements_object/create_payment_element),

This is layout when i call payment

i call api to stripe to get all charge, and the picture is the field i want to add more:
enter image description here
This is my code:

const stripeAccount = document.body.getAttribute('data-stripe-account');
const amount = document.body.getAttribute('data-stripe-amount');
const userrequest = document.body.getAttribute('data-u-r');
const returnURL = document.getElementById('URL').value;
const data = {user_request: userrequest, stripeAccount: stripeAccount, amount: amount };
let elements;
const stripe = Stripe("pk_test_51ObgQ7AapkrJHjBL5v8Q...Au17hotn4NOaI6FITTVH84auC00Cq4IfMCd",
{
  stripeAccount: stripeAccount,
}
);

initialize();
checkStatus();

document
  .querySelector("#payment-form")
  .addEventListener("submit", handleSubmit);

// Fetches a payment intent and captures the client secret
async function initialize() {
  const { clientSecret } = await fetch("/stripe/acceptPayment", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ data }),
  }).then((r) => r.json());

  elements = stripe.elements({ clientSecret });

  const billingDetails = {
    name: "messi lionel"
  }

  const paymentElementOptions = {
    layout: "tabs",
    defaultValues: {
      billingDetails: billingDetails
    }
  };

  const paymentElement = elements.create("payment", paymentElementOptions);
  paymentElement.mount("#payment-element");
}
async function handleSubmit(e) {
  e.preventDefault();
  setLoading(true);

  const { error } = await stripe.confirmPayment({
    elements,
    confirmParams: {
      return_url: returnURL,
    },
  });

  if (error.type === "card_error" || error.type === "validation_error") {
    showMessage(error.message);
  } else {
    showMessage("An unexpected error occurred.");
  }

  setLoading(false);
}

async function checkStatus() {
  const clientSecret = new URLSearchParams(window.location.search).get(
    "payment_intent_client_secret"
  );

  if (!clientSecret) {
    return;
  }

  const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);

  switch (paymentIntent.status) {
    case "succeeded":
      showMessage("Payment succeeded!");
      break;
    case "processing":
      showMessage("Your payment is processing.");
      break;
    case "requires_payment_method":
      showMessage("Your payment was not successful, please try again.");
      break;
    default:
      showMessage("Something went wrong.");
      break;
  }
}

// ------- UI helpers -------

function showMessage(messageText) {
  const messageContainer = document.querySelector("#payment-message");

  messageContainer.classList.remove("hidden");
  messageContainer.textContent = messageText;

  setTimeout(function () {
    messageContainer.classList.add("hidden");
    messageContainer.textContent = "";
  }, 4000);
}

// Show a spinner on payment submission
function setLoading(isLoading) {
  if (isLoading) {
    // Disable the button and show a spinner
    document.querySelector("#submit").disabled = true;
    document.querySelector("#spinner").classList.remove("hidden");
    document.querySelector("#button-text").classList.add("hidden");
  } else {
    document.querySelector("#submit").disabled = false;
    document.querySelector("#spinner").classList.add("hidden");
    document.querySelector("#button-text").classList.remove("hidden");
  }
}

I tried following the document but without success.

Auto Refresh in Trading View Charting Library in react

I am encountering an issue with implementing auto-refresh for a TradingView chart in a React application. I have integrated the UDF adapter API for the data feed URL, and the chart is rendering correctly. However, I am facing challenges in implementing the auto-refresh functionality.

import React, { useEffect, useState } from "react";
import { widget } from "../../charting_library";
import { connect } from "react-redux";
import datafeed from "./datafeed";

function getLanguageFromURL() {
  const regex = new RegExp("[\?&]lang=([^&#]*)");
  const results = regex.exec(window.location.search);
  return results === null
    ? null
    : decodeURIComponent(results[1].replace(/+/g, " "));
}

function TVChartContainer(props) {
  console.log("props", props);
  const [state, setState] = useState({
    symbols: props.symbols,
    pre_symbols: props.pre_symbols,
  });
  const [tvWidget, setTvWidget] = useState(null);

  const widgetOptionsFunc = (widgtProp) => {
    let symbols = widgtProp.symbols;
    if (widgtProp.pre_symbols && widgtProp.pre_symbols !== widgtProp.symbols) {
      symbols = widgtProp.symbols;
    }

    const widgetOptions = {
      debug: false,
      symbol: symbols,
      theme: props.theme === "dark" ? "Dark" : "Light",
      // BEWARE: no trailing slash is expected in feed URL
      datafeed: new window.Datafeeds.UDFCompatibleDatafeed(
        widgtProp.datafeedUrl
      ),
      interval: widgtProp.interval,
      container_id: widgtProp.containerId,
      library_path: widgtProp.libraryPath,

      locale: getLanguageFromURL() || "en",

      disabled_features: [
        "header_compare",
        "header_saveload",
        "header_settings",
        "header_undo_redo",
        "header_screenshot",
        "header_fullscreen_button",
        "main_series_scale_menu",
        "countdown",
        "go_to_date",
        "timeframes_toolbar",
      ],
      enabled_features: ["hide_resolution_in_legend"],
      charts_storage_url: widgtProp.chartsStorageUrl,
      charts_storage_api_version: widgtProp.chartsStorageApiVersion,
      client_id: widgtProp.clientId,
      user_id: widgtProp.userId,
      fullscreen: widgtProp.fullscreen,
      autosize: widgtProp.autosize,
      studies_overrides: widgtProp.studiesOverrides,
      favorites: {
        intervals: ["1H", "2H", "4H", "6H", "12H", "1D", "3D", "2D", "1W"],
        chartTypes: ["ha"],
      },
      header_compare: false,
    };

    return new widget(widgetOptions);
  };

  useEffect(() => {
    const tvWidget = widgetOptionsFunc(props, state.symbols);
    // Assuming you have a way to persist tvWidget, e.g., using state or refs
    // For simplicity, let's assume it's a state variable
    setTvWidget(tvWidget);

    // Cleanup function to remove the widget on component unmount
    return () => {
      if (tvWidget !== null) {
        tvWidget.remove();
        setTvWidget(null);
      }
    };
  }, [props, state.symbols]);

  // Function to periodically update the chart
  const autoRefreshChart = () => {
    if (tvWidget !== null) {
      tvWidget.update();
    }
  };

  useEffect(() => {
    const intervalId = setInterval(autoRefreshChart, 30000); // Auto-refresh every 30 seconds

    // Cleanup function to clear the interval on component unmount
    return () => clearInterval(intervalId);
  }, [tvWidget]);

  return <div id={props.containerId} className={"TVChartContainer"} />;
}

TVChartContainer.defaultProps = {
  interval: "1H",
  containerId: "tv_chart_container",
  datafeedUrl: "http://localhost:5000/api/chart",
  libraryPath: "/charting_library/",
  chartsStorageUrl: "https://saveload.tradingview.com",
  chartsStorageApiVersion: "1.1",
  header_widget_buttons_mode: "fullsize",
  clientId: "localhost",
  fullscreen: false,
  autosize: true,
  studiesOverrides: {},
  supportSymbolSearch: false,
  compare_symbols: false,
  disabled_features: [
    "save_chart_properties_to_local_storage",
    "volume_force_overlay",
  ],
  enabled_features: ["move_logo_to_main_pane", "study_templates"],
  disableSave: true,
};

function mapStateToProps(state) {
  return {
    theme: state.AuthReducer.switch_theme,
  };
}

export default connect(mapStateToProps)(TVChartContainer);

The auto-refresh function is intended to update the chart every 30 seconds. I have utilized setInterval within a useEffect hook to achieve this. However, it seems that the chart is not updating as expected.

How to convert obfuscated code into readable form?

So, I am trying to scrape my leetcode solution using Vanilla JS and this is what I am getting:

class Solution:    def productExceptSelf(self, nums: List[int]) -> List[int]:               length=len(nums)        auxRight=[0 for _ in range(length)]        auxRight[0]=1        i=1        while i<length:            auxRight[i]=auxRight[i-1]*nums[i-1]            i+=1        auxLeft=[0 for _ in range(length)]        auxLeft[0]=1        i=length-1        j=1        while i>0:            auxLeft[j]=auxLeft[j-1]*nums[i]            i-=1            j+=1        i=length-1        j=0        res=[]        while i>=0 and j<length:            res.append(auxLeft[i]* auxRight[j])            j+=1            i-=1        return res        

The code is not formatted obviously but I want to convert this code into a more readable manner.

I have tried every possible formatter cdn, api, etc but I am not able to figure it out. The unformatted code is stored in a variable and I want to send this raw code and receive formatted code back.

THE SCRAPED CODE CAN BE IN ANY LANGUAGE. IT SHOULD WORK ON ALL

I tried to remove my keydown event in my game in javascript but it does not have any effect

I have been building game in which the bug moves when pressed left or right. However, when game is over and I press the key the player still moves. I tried removeEventListener in my gameover function. It does not work at all.
This my code. Can you direct me how can I solve it.

const canvas = document.getElementById("screen")
const ctx = canvas.getContext("2d")

//Board Dimension
boardWidth = 1000
boardHeight = 600

//Canvas dimension
canvas.width = boardWidth
canvas.height = boardHeight

// Bug Dimension
const bugWidth = 50
const bugHeight = 50

//Index of Bug and Obstacle.
obstacleIndex = 3
let bugIndex = 2

//GameOver
let isGameOver =false  

//wires
const wires =  [
    {x:canvas.width/5,y:canvas.height},
    {x:2*canvas.width/5,y:canvas.height},
    {x:3*canvas.width/5,y:canvas.height},
    {x:4*canvas.width/5,y:canvas.height}
]

const bug  = {x:wires[bugIndex].x - bugWidth * 0.5,
              y:canvas.height * 0.75 - bugHeight * 0.5}

// Obstacle Dimension
const obstacleWidth = 50;
const obstacleHeight = 50;

const obstacles_list = [
    
]

ctx.strokeStyle = "#000000"

ctx.lineWidth = 3;

//draw line function
function draw_line(){  
for(let i in wires){
    ctx.beginPath()
    ctx.moveTo(wires[i].x,0)
    ctx.lineTo(wires[i].x,canvas.height)  
    ctx.stroke()
}
}

function createNewObstacle() {
    let randomWireIndex = Math.floor(Math.random() * wires.length);
    let obstacleX = wires[randomWireIndex].x;
    let obstacleY = obstacleHeight;
    dy = 5
    return {x: obstacleX, y: obstacleY,dy:dy}
}

function isCollision(bug, obstacle) {
    // Check if the bug's rectangle intersects with the obstacle's rectangle
    return (
        bug.x < obstacle.x + obstacleWidth &&
        bug.x + bugWidth > obstacle.x &&
        bug.y < obstacle.y + obstacleHeight &&
        bug.y + bugHeight > obstacle.y
    );
}


// function to draw obstacles
function drawObstacles() {
 //Use setInterval instead of Math.random() <0.028
    if( Math.random() <0.028){
        obstacles_list.push(createNewObstacle()) 
    }
    ctx.fillStyle = "red";
    for (let obstacle of obstacles_list) {
        ctx.fillRect(
            obstacle.x - obstacleWidth / 2,
            obstacle.y - obstacleHeight / 2,
            obstacleWidth,
            obstacleHeight
            )
        }
    }

function updateObstacles() {
    for (let obstacle of obstacles_list) {
        
        obstacle.y += obstacle.dy;
        console.log(isGameOver)
        if (isCollision({ x: wires[bugIndex].x, y: canvas.height * 0.75 }, obstacle)) {
            // Handle collision (e.g., end the game or reduce lives)
            isGameOver = true
            gameOver()
            change_bug_line(true)
        }

        if (obstacle.y > boardHeight) {
            obstacles_list.splice(obstacles_list.indexOf(obstacle), 1);
        }
        
    }
}
function draw_bug(shouldDraw) {
    const rectX = wires[bugIndex].x - bugWidth * 0.5;
    const rectY =  canvas.height * 0.75 - bugHeight * 0.5;
    if (shouldDraw) {
        ctx.fillStyle = "green";
        ctx.fillRect(rectX, rectY, bugWidth, bugHeight);
    } else {
        ctx.clearRect(rectX, rectY, bugWidth, bugHeight);
    }

}


function update_line(key){
    switch(key){
        case "ArrowLeft":
            draw_bug(false)
            bugIndex--
            if(bugIndex<0) bugIndex = 0
        break;

        case "ArrowRight":
            draw_bug(false)
            bugIndex++
            if(bugIndex>=wires.length) bugIndex = wires.length-1
        break;

    }
    draw_bug(true)
}


function change_bug_line(isGameOver){
    if(!isGameOver){window.document.addEventListener("keydown",(e)=>{
        update_line(e.key)
    })

}}

function displayGameOverMessage() {
    ctx.fillStyle = "black";
    ctx.font = "30px Arial";
    ctx.textAlign = "center";
    ctx.fillText("Game Over", canvas.width / 2, canvas.height / 2);
}
function gameOver(){
        clearInterval(timerID)
        displayGameOverMessage(); 
}


function gameLoop() {
 // Only continue the game loop if the game hasn't ended
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        draw_line();
        draw_bug(true);
        updateObstacles();
        drawObstacles();
    
}

change_bug_line() //this loops contains the key event listener
const timerID= setInterval(gameLoop,1000/60) //renders my frame


I had tried adding removeEventListner and i though the frame of the game of would be still and keyboard would not work but still the frame was still. The key event was still capturing

Parallel API calls and updating an array of images as each call returns

I have an array of IDs in react. For each of these IDs I need to make an API call to get a corresponding image url. The API calls can take a long time. How do I build the app so that the list of images is displayed asynchronously as each API call returns?

So far I’ve tried to use array.map() to call the API with Promise.all() to wait for all results. Then I’d use setImageList([...results]) to update the state. This waits for all API calls to have returned. Can I change that so that the state gets updated as each API call returns?