Is there a better way to connect socke.io client in react?

I am trying to set up a real time chat application using socket.io, I have been having issues with the socket connection on frontend, I need a bit clarification on how to go about it.
on the backend
backend/socket.js

   const { Server } = require("socket.io");
   const http = require("http");
   const express = require("express");
   const socketJwt = require("./middleware/socketJWT");

   const app = express();
   const server = http.createServer(app);
   const io = new Server(server, {
     cors: {
       origin:
         process.env.NODE_ENV === "production"
           ? false
           : [
            "http://localhost:5500",
            "http://127.0.0.1:5500",
            "http://localhost:3000",
          ],
       methods: ["GET", "POST"],
       transports: ["websocket", "polling"],
       credentials: true,
     },
     allowEIO3: true,
   });
  io.engine.use(socketJwt);

   io.on("connection", (socket) => {
     console.log(socket.id);
    const user = socket.request.user;
    const userSocketMap = {};
    if (user != "undefined") userSocketMap[user] = user;
    io.emit("getOnlineUsers", Object.keys(userSocketMap));
    console.log(user);
   });

   module.exports = { server, app };

backend/app.js

    require("dotenv").config();
    const { server, app } = require("./newSocket");
    const express = require("express");
    const path = require("path");
    const PORT = process.env.PORT || 3500;
    const { logger, logEvents } = require("./middleware/logger");
    const errorHandler = require("./middleware/errorHandler");
    const connectDB = require("./config/dbConn");
    const mongoose = require("mongoose");
    const cors = require("cors");
    const corsOptions = require("./config/corsOptions");
    const cookieParser = require("cookie-parser");
    const verifyJwt = require("./middleware/verifyJwt");

    app.use(cors(corsOptions));
    app.use(express.json());
    app.use(cookieParser());
    app.use("/", express.static(path.join(__dirname, "/public")));
    app.use("/", require("./routes/root"));
    app.use("/contacts", require("./routes/contactRoutes"));
    app.use("/users", require("./routes/useRoutes"));
    app.use("/login", require("./routes/authRoutes"));
    app.use("/refresh", require("./routes/refreshRoute"));
    app.use("/logout", require("./routes/logOutRoute"));
    app.use("/employees", require("./routes/api/employees"));
    app.use(logger);

    app.all("*", (req, res) => {
    res.status(404);
    if (req.accepts("html")) {
      res.sendFile(path.join(__dirname, "views", "404.html"));
      } else if (req.accepts("json")) {
       res.json({ message: "404 Not found" });
      } else {
        res.type("txt").send("404 Not Found");
        console.log("res.headersSent");
     }
});

app.use(errorHandler);

mongoose.connection.once("open", () => {
  console.log("Connected to MongoDB");
});
mongoose.connection.on("error", (err) => {
  console.log(err);
  logEvents(
    `${err.no}:${err.code}t${err.syscall}t${err.hostname}`,
    "mongoErrLog.log"
  );
});
server.listen(PORT, () => {
  connectDB();
  console.log(`Server running on port ${PORT}`);
});
`

frontend/src/hooks/socketContext.js
`
import { createContext, useContext, useEffect, useState } from "react";
import { io } from "socket.io-client";
import { useAuth } from "./useAuth";

const url = "ws://localhost:3500";
const SocketContext = createContext();
export const SocketContextProvider = ({ children }) => {
  const [socket, setSocket] = useState(null);
  const [onlineUsers, setOnlineUsers] = useState([]);
  const { user, token } = useAuth();

  useEffect(() => {
    if (user) {
      const socket = io(url, {
        autoConnect: false,
        reconnection: false,
        extraHeaders: {
          authorization: `bearer ${token}`,
        },
      });
      setSocket(socket);

      socket.on("getOnlineUsers", (users) => {
        setOnlineUsers(users);
      });

      return () => socket.close();
    } else {
      if (socket) {
        socket.close();
        setSocket(null);
      }
    }
  }, [user, token, socket]);

  return (
    <SocketContext.Provider value={{ socket, onlineUsers }}>
      {children}
    </SocketContext.Provider>
  );
};

export const useSocket = () => {
  return useContext(SocketContext);
};
`

frontend/src/index.js
`
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import "bootstrap/dist/css/bootstrap.css";
import { BrowserRouter } from "react-router-dom";
import { SocketContextProvider } from "./hooks/socketContext";
import { AuthProvider } from "./hooks/useAuth";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <AuthProvider>
        <SocketContextProvider>
          <App />
        </SocketContextProvider>
      </AuthProvider>
    </BrowserRouter>
  </React.StrictMode>
);

I created a context and established the socket connection there which I shared across the application, however the socket has failed to connect. the getOnlineUsers event emitted in the server is not listened to by the client, also the server has failed to receive any connection event from the client.

please, help me out, I have been finding it difficult to ask questions here, am begging you guys to help. thanks in anticipation
if you can show me how to do the connection with redux it will be nice.

Change the value of a checkbox using a Java script

can I change the value of a checkbox using a Java script in the DOM of the browser page?

It is necessary that the value remains the next time the form is loaded.

I tried several methods, but it only worked to visually check the box. When you clicked again, the checkbox was updated to a real one, and when submitting the form, a message was displayed that there was no checkmark at all

building a Chrome extension| Can popup page be sandboxed page?

I’m trying to build with flutter simple chrome extension that connects to firebase and performing some crud. Google’s CSP policy making my life hard by preventing me from loading scripts from external sources. In my case I don’t need access to all chrome’s apis.
Can I define that my popup page and sandbox page are the same page? And may google reject my app from extensions store?

I’ve tried to save all firebase script’s locally, but it didn’t worked despite not throwing any errors..

Creating a live collaboration web page [duplicate]

This post is hidden. You deleted this post 3 days ago.

Closed. This question is seeking recommendations for software libraries, tutorials, tools, books, or other off-site resources. It does not meet Stack Overflow guidelines. It is not currently accepting answers.


I want to create a normal web page with images, buttons, elements, etc. I want to be able to turn on live mode, and then have this page be interactive with multiple users.

So I can start a session, send the link to others, let’s say 5 people, and then we can all click around on the page and the result of this clicking around will appear for everyone. So if you click on a button and a modal opens, it needs to open for everyone else. The idea here for what needs to be “real-time” is simply like this, and nothing complicated, just a static web page.

An example is, if I click a button and the background changes to red, it changes to red for all live users, and also the ability to track cursors with names like Miro Board.

All the tutorials and articles I’ve seen, like using collaboration engine, or meteor.js, or others, are purely for canvas/document collaboration like Google Docs, Miro Board, etc.

What I want to know is,
1. Is this possible, to have live collaboration on a web elements like button or navigation rather than a form or a canvas, if so how would I do this?
3. What would the logic flow for a code sample for this look like? What data do I track, send to the server, and what data do the other users receive, etc?

Functions not using most recent state in React functional component

I am converting a class component to a functional component but I am having an issue where state values from useState are not the most recent values inside a another function. Because the functions need to be called dynamically, they are first defined in a mapping to an ID and invoked using the current ID. Before, I solved this by binding the validator functions to the component itself. However as a functional component, this is not possible.

Here is a simplified version of the issue:

export default function App(props) {
  const [currentStage, setStage] = useState(0);
  const [stageOrder, setStageOrder] = useState([]);
  const [inputName, setInput] = useState(null);
  const [invalid, setInvalid] = useState(false);

  const stageDefinitions = {
    [StageType.ONE]: { id: StageType.ONE, validator: validateOne },
    [StageType.TWO]: { id: StageType.TWO, validator: validateTwo },
  };

  useEffect(() => {
    // written like this for readability and make it easier to change the order in the future
    let order = props.flag ? [StageType.ONE, StageType.TWO] : [StageType.ONE];

    order = order.map((s) => stageDefinitions[s]);
    setStageOrder(order);
  }, []);

  function nextStage() {
    if (currentStage === stageOrder.length - 1) return;

    const stage = stageOrder[currentStage];
    const isValid = stage.validator();

    if (isValid) setStage(currentStage + 1);
    setInvalid(!isValid);
  }

  function validateOne() {
    // problem is here; inputName remains null when called from nextStage
    console.log("inputName", inputName);
    return inputName && inputName.length > 1;
  }

  function validateTwo() {
    return props.two > 1;
  }

  function handleClick() {
    setInput(`${Math.random()}`);
  }

  return (
    <div>
      <div>Value: {inputName}</div>
      {invalid && <div style={{ color: "red" }}>INVALID</div>}

      <div>Stage: {currentStage}</div>

      <button onClick={handleClick}>Set Value</button>
      <button onClick={nextStage}>Next Stage</button>
    </div>
  );
}

This can also be found on codesandbox.

I’ve tried using useCallback and defining stageDefinitions in the state. The ultimate goal is that when a validator is called from nextStage, it uses the current value of inputName.

Threejs splited torus is showing black dotted

my goal is to split the shape e.g. like a torus but it could be a circle triangle etc. I want to split the shape by using a custom plane. Once the torus is split-into two parts both parts need to be draggable separately.

So far I am able to split the torus but

  1. both parts torusAbove and torusBelow are displayed in black dott. It is not taking colour or texture. What is the problem here?
  2. Another issue is if I would like to highlight the intersection of tours and planes with some colour e.g. green, how can I achieve it?
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Three.js Plane and Torus Split Example</title>
  <style>
    body {
      margin: 0;
    }
    
    canvas {
      display: block;
    }
  </style>
</head>

<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  <script src="https://cdn.rawgit.com/mrdoob/three.js/r128/examples/js/controls/DragControls.js"></script>
  <script src="https://cdn.rawgit.com/mrdoob/three.js/r128/examples/js/controls/OrbitControls.js"></script>
  <script>
    // 1. Set up the scene, camera, and renderer
    const scene = new THREE.Scene();
    // Set the camera's perspective
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    // Set up the WebGL renderer
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    // Append the renderer's canvas element to the document body
    document.body.appendChild(renderer.domElement);
    // Set the clear color for the renderer (background color)
    renderer.setClearColor(0x00ffff); // Black background
    // 2. Create the plane geometry and material
    const planeGeometry = new THREE.PlaneGeometry(5, 5); // 5x5 units plane
    const planeMaterial = new THREE.MeshStandardMaterial({
      color: 0x00ff00
    });
    const plane = new THREE.Mesh(planeGeometry, planeMaterial);
    scene.add(plane);
    // Position the plane
    plane.rotation.x = -Math.PI / 2; // Rotate the plane to be horizontal
    // 3. Create the torus geometry and material
    const torusGeometry = new THREE.TorusGeometry(1, 0.4, 100, 100); // Increased radialSegments to 32
    const torusMaterial = new THREE.MeshStandardMaterial({
      color: 0xffff00,
      roughness: 0.5,
      metalness: 0.5
    }); // Red color, with some roughness and metalness
    let torus = new THREE.Mesh(torusGeometry, torusMaterial);
    scene.add(torus);
    // Position the torus
    torus.position.set(0, 1, 0); // Position the torus above the plane
    // 4. Add a light source
    const ambientLight = new THREE.AmbientLight(0x404040); // Soft white light
    scene.add(ambientLight);
    const pointLight = new THREE.PointLight(0xffffff, 1);
    pointLight.position.set(5, 5, 5);
    scene.add(pointLight);
    // Position the camera
    camera.position.set(0, 5, 5); // Place the camera at (0, 5, 5)
    camera.lookAt(0, 0, 0); // Make the camera look at the origin
    // 5. Enable OrbitControls for better navigation
    const orbitControls = new THREE.OrbitControls(camera, renderer.domElement);
    // 6. Function to split the torus
    function splitTorus() {
      const planeHeight = plane.position.y;
      const posAttr = torus.geometry.attributes.position;
      const verticesAbove = [];
      const verticesBelow = [];
      for (let i = 0; i < posAttr.count; i++) {
        const vertex = new THREE.Vector3().fromBufferAttribute(posAttr, i);
        vertex.applyMatrix4(torus.matrixWorld);
        if (vertex.y >= planeHeight) {
          verticesAbove.push(vertex);
        } else {
          verticesBelow.push(vertex);
        }
      }
      const geometryAbove = new THREE.BufferGeometry().setFromPoints(verticesAbove);
      const geometryBelow = new THREE.BufferGeometry().setFromPoints(verticesBelow);
      const materialAbove = new THREE.MeshStandardMaterial({
        color: 0x0000ff,
        roughness: 0.5,
        metalness: 0.5
      }); // Blue color, with some roughness and metalness
      const materialBelow = new THREE.MeshStandardMaterial({
        color: 0xffff00,
        roughness: 0.5,
        metalness: 0.5
      }); // Yellow color, with some roughness and metalness
      const torusAbove = new THREE.Mesh(geometryAbove, materialAbove);
      const torusBelow = new THREE.Mesh(geometryBelow, materialBelow);
      scene.remove(torus);
      scene.remove(plane);
      scene.add(torusAbove);
      scene.add(torusBelow);
      torusAbove.name = 'torusAbove';
      torusBelow.name = 'torusBelow';
      return [torusAbove, torusBelow];
    }
    let [torusAbove, torusBelow] = splitTorus();
    // 7. Enable DragControls for both parts
    const dragControlsAbove = new THREE.DragControls([torusAbove], camera, renderer.domElement);
    const dragControlsBelow = new THREE.DragControls([torusBelow], camera, renderer.domElement);
    // Highlight dragged objects
    dragControlsAbove.addEventListener('dragstart', function(event) {
      event.object.material.emissive.set(0xaaaaaa);
    });
    dragControlsAbove.addEventListener('dragend', function(event) {
      event.object.material.emissive.set(0xff00ff);
    });
    dragControlsBelow.addEventListener('dragstart', function(event) {
      event.object.material.emissive.set(0xaaaaff);
    });
    dragControlsBelow.addEventListener('dragend', function(event) {
      event.object.material.emissive.set(0x0000ff);
    });
    // 8. Render the scene
    function animate() {
      requestAnimationFrame(animate);
      renderer.render(scene, camera);
    }
    animate();
    // Handle window resize
    window.addEventListener('resize', () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    });
  </script>
</body>

</html>

Here is my sample code

Need help having multiple drop down buttons

I have a very simple website where I have a picture of my wife and I for the last 19 years that we’ve been together. A picture per month. It loads using lazy load which works great. I added anchor links (is that what they’re called?) so you can skip from year to year from the header. But imagine now I have 19 links up there. Friend of mine told me I should look into dropdown menu. I was able to find an example online and it works. But now it gives me 19 links vertically instead of horizontally. So I thought I would break it down into multiple subcategories. 2020-2024, 2010-2019 and 2005-2009. I got it “working” individually, but as soon as I enable all three, only the last one shows. What am I missing here? Please note I have very little css/js/html experience. I can follow directions well but I don’t know what’s natively in the language that should be obvious to someone with more experience.

Here is the relevant portions of the page. As I said above, I can get each of the three subcategories to work, but not all three at once.

CSS

<style>
/* Dropdown Button */
.dropbtn {
  background-color: white;
  color: black;
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
  box-shadow: 0px 4px 4px 0px rgba(0,0,0,0.2);
}

/* Dropdown button on hover & focus */
.dropbtn:hover, .dropbtn:focus {
  background-color: white;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
}

/* The container <div> - needed to position the dropdown content */
.dropdown {
  position: relative;
  display: inline-block;
}

/* Dropdown Content (Hidden by Default) */
.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

/* Links inside the dropdown */
.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

/* Change color of dropdown links on hover */
.dropdown-content a:hover {background-color: #ddd;}

/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
.show {display:block;}
</style>

JavaScript

<script>
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function doDropdown() {
  /*document.getElementById("myDropdown").classList.toggle("show");*/
  document.getElementById("dropDown2020").classList.toggle("show");
  document.getElementById("dropDown2010").classList.toggle("show");
  document.getElementById("dropDown2000").classList.toggle("show");
}

function showDecade2020(){
    document.getElementById("myDropdown2020").classList.toggle("show");
}

function showDecade2010(){
    document.getElementById("myDropdown2010").classList.toggle("show");
}

function showDecade2000(){
    document.getElementById("myDropdown2000").classList.toggle("show");
}

// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
  if (!event.target.matches('.dropbtn')) {
    var dropdowns = document.getElementsByClassName("dropdown-content");
    var i;
    for (i = 0; i < dropdowns.length; i++) {
      var openDropdown = dropdowns[i];
      if (openDropdown.classList.contains('show')) {
        openDropdown.classList.remove('show');
      }
    }
  }
}
</script>

HTML

<div class="dropdown">
          <button onclick="doDropdown()" class="dropbtn">Jump to a specific year...</button>                  
          <div id="dropDown2020" class="dropdown-content">
            <button onclick="showDecade2020()" class="dropbtn">2020-2024</button>
            <div id="myDropdown2020" class="dropdown-content">
            <a href="#2024">2024</a>
            <a href="#2023">2023</a>
            <a href="#2022">2022</a>
            <a href="#2021">2021</a>
            <a href="#2020">2020</a>
            </div>
          </div>
          <div id="dropDown2010" class="dropdown-content">
            <button onclick="showDecade2010()" class="dropbtn">2010-2019</button>
            <div id="myDropdown2010" class="dropdown-content">
            <a href="#2019">2019</a>
            <a href="#2018">2018</a>
            <a href="#2017">2017</a>
            <a href="#2016">2016</a>
            <a href="#2015">2015</a>
            <a href="#2014">2014</a>
            <a href="#2013">2013</a>
            <a href="#2012">2012</a>
            <a href="#2011">2011</a>
            <a href="#2010">2010</a>
            </div>
          </div>
          <div id="dropDown2000" class="dropdown-content">
            <button onclick="showDecade2000()" class="dropbtn">2005-2009</button>
            <div id="myDropdown2000" class="dropdown-content">
            <a href="#2009">2009</a>
            <a href="#2008">2008</a>
            <a href="#2007">2007</a>
            <a href="#2006">2006</a>
            <a href="#2005">2005</a>
            </div>
          </div>         
        </div>

How to Access the Selected Time Range of Grafana UI for Plugin Typescript

I want to access the selected time range on the Grafana UI in my Typescript plugin.

Here is my current code:

import { DataSourceInstanceSettings, CoreApp, ScopedVars } from '@grafana/data'; import { DataSourceWithBackend, getTemplateSrv } from '@grafana/runtime';

import { MyQuery, MyDataSourceOptions, DEFAULT_QUERY } from './types';

export class DataSource extends DataSourceWithBackend<MyQuery, MyDataSourceOptions> { constructor(instanceSettings: DataSourceInstanceSettings<MyDataSourceOptions>) { super(instanceSettings); console.log('DataSource constructor', instanceSettings); }

getDefaultQuery(_: CoreApp): Partial<MyQuery> { return DEFAULT_QUERY; }

applyTemplateVariables(query: MyQuery, scopedVars: ScopedVars): Record<string, any> { console.log(query, 'qery'); console.log(scopedVars, 'scopedVars');
// const from = request.range?.from.valueOf() ?? new Date().valueOf();
// const to = request.range?.to.valueOf() ?? new Date().valueOf();

// console.log(`Querying for range from ${new Date(from).toISOString()} to ${new Date(to).toISOString()}`);

return {
  ...query,

  queryText: getTemplateSrv().replace(query.queryText, scopedVars),
};
}

filterQuery(query: MyQuery): boolean { // if no query has been provided, prevent the query from being executed return !!query.queryText; } }

How can I access the time range?

react: imports not working in another file not working

what may be the cause of these imports not working in my react app?

index.jsx

import { 
  getData,
  getOne,
} from "../../../server/config/db.js";
import * as mysql from "mysql2";

db.js snippet


export async function getData() {
  const [rows] = await pool.query(`
  SELECT * FROM claim`);
  return rows;
}

export async function getOne(id) {
  const [rows] = await pool.query(`
  SELECT * 
  FROM claim
  WHERE id = ?
  `, [id]);

  return rows[0];
}

the import works form server/index.js

expecting to access the exported functions from the index.jsx file

Qualtrics – Carrying forward randomized order of subset of mc response options to next question, while preserving exclusive anchored options

I would like to do the following with multiple choice, select all, questions Q10 and Q11 (screenshot below):
Question Q10 and Q11

Step 1. Randomize the order of the 1st 7 response options (the brands) while anchoring the last 2 response options both of which must be “exclusive” response options (i.e., when either 8 or 9, the last options, is selected, no other choices can be selected). This Step can be done using advanced randomization for Q10.

However, basic functionality in Qualtrics won’t accomplish Step 2, below.

Step 2. I want to present the same randomized order of the 1st 7 response options (the brands) from Q10 to Q11 (i.e., the randomized order of brands in Q11 must appear in the same randomized order as they appeared in Q10) while, at the same time, anchoring the last 2 response options, both of which must still be “exclusive” response options.

Step 2 cannot be done using “carry forward choices” because the “advanced randomization” from Q10 cannot be carried over to Q11 while ensuring that options 8 and 9, the last options, are exclusive options. In other words, when using Qualtrics standard features, using “carry forward choices” presents options 8 and 9 as non-exclusive response options in Q11 (I don’t know why it can’t preserve the exclusive options).

Question 1: How can I accomplish Step 2? What is the simplest way, JS or Survey Flow? If JS, what code would be required? (I’m novice at JS)

Question 2: Additionally, how can I record the order that response options were presented in Q10 and Q11 in the output of the dataset? (Ideally it would be a single variable and data would appear as, e.g., “1,4,5,2,3,7,6,8,9”)

Inconsistent State Synchronization with Custom useLocalStorage Hook in React

I’m encountering an issue with state synchronization in a React application using a custom useLocalStorage hook. The App component correctly logs changes to the counter state, while another hook trying to access the same state doesn’t log these changes, even though the state is supposed to be shared via local storage.

codesandbox here

Here’s the code:

import { useState, useEffect } from "react";

const useLocalStorage = (key, initialValue) => {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error("Failed to read from localStorage", error);
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      const valueToStore =
        value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error("Failed to write to localStorage", error);
    }
  };

  useEffect(() => {
    const handleStorageChange = (event) => {
      if (event.key === key && event.newValue) {
        setStoredValue(JSON.parse(event.newValue));
      }
    };

    window.addEventListener("storage", handleStorageChange);
    return () => window.removeEventListener("storage", handleStorageChange);
  }, [key]);

  return [storedValue, setValue];
};

const useCounter = () => {
  const [counter, setCounter] = useLocalStorage("counter", 0);

  const incrementCounter = () => setCounter((prev) => (prev += 1));

  return { counter, incrementCounter };
};

const useInput = () => {
  const [input, setInput] = useState("");
  const { counter } = useCounter();

  useEffect(() => {
    console.log("useEffect in useInput"); // this does not run as I type
  }, [counter]);

  return { input, setInput };
};

export default function App() {
  const { input, setInput } = useInput();
  const { counter, incrementCounter } = useCounter();

  useEffect(() => {
    console.log("useEffect in App"); // this runs as I type
  }, [counter]);

  const handleInput = (value) => {
    incrementCounter();
    setInput(value);
  };

  return <input onChange={(e) => handleInput(e.target.value)} value={input} />;
}

The App component correctly logs changes to the counter state, but the useEffect inside the useInput hook does not log these changes. I expected both useEffect hooks to be triggered when counter is incremented. Why is this happening, and how can I ensure the state is consistently shared and updated across components?

Why is pg library not pulling database from Postgres?

I need to change port to 54023 for it to run on the right port.
**when i print out quiz after trying to pull data, it is empty.
**

db.connect() is not logging any message.

pg library is correctly installed.

I used pgAdmin 4, the Database is named ‘world’. The Table is named ‘capitals’

console.log("query excuted"); is not printed nor did console.log("hi");

import express from "express";
import bodyParser from "body-parser";
import pg from "pg";

const db = new pg.Client({
  user: "postgres",
  host: "localhost",
  database: "world",
  password: "****", 
  port: 54023,
});

const app = express();
const port = 3000;

db.connect()
  .then(() => console.log('Connected to the database'))
  .catch(err => console.error('Failed to connect to the database:', err));

let quiz = [];
console.log('About to execute query');

db.query("SELECT * FROM capitals", (err, res) => {
  if (err) {
    console.error("Error executing query", err.stack);
    console.log("hi");
  } else {
    console.log("query excuted");

    quiz = res.rows;
    console.log(quiz);

  }
  db.end();
});
let totalCorrect = 0;
console.log(quiz);

// Middleware
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));

let currentQuestion = {};

// GET home page
app.get("/", (req, res) => {
  totalCorrect = 0;
  nextQuestion();
  console.log(currentQuestion);
  res.render("index.ejs", { question: currentQuestion });
});

// POST a new post
app.post("/submit", (req, res) => {
  let answer = req.body.answer.trim();
  let isCorrect = false;
  if (currentQuestion.capital.toLowerCase() === answer.toLowerCase()) {
    totalCorrect++;
    console.log(totalCorrect);
    isCorrect = true;
  }

  nextQuestion();
  res.render("index.ejs", {
    question: currentQuestion,
    wasCorrect: isCorrect,
    totalScore: totalCorrect,
  });
});

function nextQuestion() {
  const randomCountry = quiz[Math.floor(Math.random() * quiz.length)];
  currentQuestion = randomCountry;
  console.log(currentQuestion);
}

app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});

Well the error initially started with incorrect port number, which i changed. Then the error tells me the question, which is passed on by app.get, does not existed. Then, i looked at the quiz – it turns out it did not pull the database correctly. It is empty. So i look into db.query, it looks like it is not executing each of the lines. Then i look at db.connect(), nothing is printing either?

Click event doesn’t happen until I click the button 2-3 times

I am writing a calculator for ADHD medication dosages. However, when I press “Convert!” I have to click it several times for the placeholder text to appear. What’s going on? Nothing I try seems to work but to be completely honest I have no idea what to do in this situation – please advise.

I tried changing onclick in the HTML tag to am event listener in JS but it has not helped.

function convertRitalinLA() {
  var convertMedications = document.getElementById("convertMedications").value;
  var dosages = document.getElementById("dosages").value;
  var toTheseMedications = document.getElementById("toTheseMedications").value;
  var placeholder = document.getElementById("placeholder");

  if (convertMedications === "Ritalin LA") {
    if (toTheseMedications === "Ritalin") {
      if (dosages === "10mg") {
        console.log("10mg")
        placeholder.innerHTML = "Your new dose of Ritalin is 10mg."
      } else if (dosages === "20mg") {
        console.log("20mg")
        placeholder.innerHTML = "Your new dose of Ritalin is 20mg."
      } else if (dosages === "30mg") {
        console.log("30mg")
        placeholder.innerHTML = "Your new dose of Ritalin is 30mg."
      } else if (dosages === "40mg") {
        console.log("40mg")
        placeholder.innerHTML = "Your new dose of Ritalin is 40mg."
      } else if (dosages === "60mg") {
        console.log("60mg")
        placeholder.innerHTML = "Your new dose of Ritalin is 60mg."
      } else if (toTheseMedictions === "Concerta") {
        if (dosages = "10mg") {
          console.log("36mg")
          placeholder.innerHTML = "Your new dose of Concerta is 36mg."
        } else if (dosages === "20mg") {
          console.log("72mg")
          placeholder.innerHTML = "Your new dose of Concerta is 72mg."
        } else if (dosages === "30mg") {
          console.log("108mg")
          placeholder.innerHTML = "Your new dose of Concerta is 108mg"
        } else if (dosages === "40mg") {
          console.log("Warning! Dose exceeds maximum daily dose.")
          placeholder.innerHTML = "Warning! Dose exceeds maximum daily dose."
        } else if (dosages === "60mg") {
          console.log("Warning! Dose exceeds maximum daily dose.")
          placeholder.innerHTML = "Warning! Dose exceeds maximum daily dose."
        }
      } else if (toTheseMedications === "Dexamfetamine") {
        if (dosages = "10mg") {
          console.log("5mg")
          placeholder.innerHTML = "Your new dose of Concerta is 5mg."
        } else if (dosages === "20mg") {
          console.log("10mg")
          placeholder.innerHTML = "Your new dose of Concerta is 10mg."
        } else if (dosages === "30mg") {
          console.log("15mg")
          placeholder.innerHTML = "Your new dose of Concerta is 15mg."
        } else if (dosages === "40mg") {
          console.log("20mg")
          placeholder.innerHTML = "Your new dose of Concerta is 0mg."
        } else if (dosages === "60mg") {
          console.log("30mg")
          placeholder.innerHTML = "30mg"
        }
      } else if (toTheseMedications === "Vyvanse") {
        if (dosages = "10mg") {
          console.log("20mg")
          placeholder.innerHTML = "20mg"
        } else if (dosages === "20mg") {
          console.log("30mg")
          placeholder.innerHTML = "30mg"
        } else if (dosages === "30mg") {
          console.log("40mg")
          placeholder.innerHTML = "40mg"
        } else if (dosages === "50mg") {
          console.log("60mg")
          placeholder.innerHTML = "60mg"
        } else if (dosages === "60mg") {
          console.log("70mg")
          placeholder.innerHTML = "70mg"
        }
      }
    }
  } else if (toTheseMedications === "Ritalin LA") {
    console.log("Error.")
    placeholder.innerHTML = "Error."
  }
}

function convertRitalin() {
  var convertMedications = document.getElementById("convertMedications").value;
  var dosages = document.getElementById("dosages").value;
  var toTheseMedications = document.getElementById("toTheseMedications").value;
  var placeholder = document.getElementById("placeholder");

  if (convertMedications === "Ritalin") {
    if (toTheseMedications === "Ritalin LA") {
      if (dosages === "5mg") {
        console.log("10mg")
        placeholder.innerHTML = "10mg"
      } else if (dosages === "10mg") {
        console.log("20mg")
        placeholder.innerHTML = "20mg"
      } else if (dosages === "30mg") {
        console.log("60mg")
        placeholder.innerHTML = "46mg"
      } else if (dosages === "40mg") {
        console.log("8mg")
        placeholder.innerHTML = "80mg"
      } else if (dosages === "50mg") {
        console.log("100mg")
        placeholder.innerHTML = "100mg"
      }
    } else if (toTheseMedications === "Concerta") {
      if (dosages === "5mg") {
        console.log("18mg")
        placeholder.innerHTML = "18mg"
      } else if (dosages === "10mg") {
        console.log("36mg")
        placeholder.innerHTML = "36mg"
      } else if (dosages === "20mg") {
        console.log("72mg")
        placeholder.innerHTML = "72mg"
      } else if (dosages === "30mg") {
        console.log("108mg")
        placeholder.innerHTML = "108mg"
      } else if (dosages === "40mg") {
        console.log("Warning! Dose exceeds maximum daily dose.")
        placeholder.innerHTML = "Warning! Dose exceeds maximum daily dose."
      }
    } else if (toTheseMedications === "Dexamfetamine") {
      if (dosages === "5mg") {
        console.log("5mg")
        placeholder.innerHTML = "5mg"
      } else if (dosages === "10mg") {
        console.log("10mg")
        placeholder.innerHTML = "10mg"
      } else if (dosages === "20mg") {
        console.log("20mg")
        placeholder.innerHTML = "20mg"
      } else if (dosages === "30mg") {
        console.log("38mg")
        placeholder.innerHTML = "38mg"
      } else if (dosages === "40mg") {
        console.log("40mg")
        placeholder.innerHTML = "40mg"
      }
    } else if (toTheseMedications === "Vyvanse") {
      if (dosages === "5mg") {
        console.log("20mg")
        placeholder.innerHTML = "20mg"
      } else if (dosages === "10mg") {
        console.log("30mg")
        placeholder.innerHTML = "30mg"
      } else if (dosages === "20mg") {
        console.log("50mg")
        placeholder.innerHTML = "50mg"
      } else if (dosages === "30mg") {
        console.log("70mg")
        placeholder.innerHTML = "70mg"
      } else if (dosages === "40mg") {
        console.log("Warning! Dose exceeds maximum daily dose.")
        placeholder.innerHTML = "Warning! Dose exceeds maximum daily dose."
      }
    }
  }
}

function convertDexamfetamine() {
  var convertMedications = document.getElementById("convertMedications").value;
  var dosages = document.getElementById("dosages").value;
  var toTheseMedications = document.getElementById("toTheseMedications").value;
  var placeholder = document.getElementById("placeholder");

  if (convertMedications === "Dexamfetamine") {
    if (toTheseMedications === "Ritalin") {
      if (dosages === "10mg") {
        console.log("10mg")
        placeholder.value = "10mg"
      } else if (dosages === "20mg") {
        console.log("20mg")
        placeholder.value = "20mg"
      } else if (dosages === "30mg") {
        console.log("30mg")
        placeholder.innerHTML = "30mg"
      } else if (dosages === "40mg") {
        console.log("40mg")
        placeholder.innerHTML = "40mg"
      } else if (dosages === "50mg") {
        console.log("60mg")
        placeholder.innerHTML = "50mg"
      } else if (dosages === "60mg") {
        console.log("60mg")
        placeholder.innerHTML = "60mg"
      }
    }
    if (toTheseMedications === "Ritalin LA") {
      if (dosages === "10mg") {
        console.log("20mg")
        placeholder.innerHTML = "20mg"
      } else if (dosages === "20mg") {
        console.log("40mg")
        placeholder.innerHTML = "40mg"
      } else if (dosages === "30mg") {
        console.log("60mg")
        placeholder.innerHTML = "60mg"
      } else if (dosages === "40mg") {
        console.log("80mg")
        placeholder.innerHTML = "80mg"
      } else if (dosages === "50mg") {
        console.log("100mg")
        placeholder.innerHTML = "100mg"
      } else if (dosages === "60mg") {
        console.log("120mg")
        placeholder.innerHTML = "120mg"
      }
    }

    if (toTheseMedications === "Concerta") {
      if (dosages === "10mg") {
        console.log("36mg")
        placeholder.innerHTML = "36mg"
      } else if (dosages === "20mg") {
        console.log("72mg")
        placeholder.innerHTML = "72mg"
      } else if (dosages === "30mg") {
        console.log("108mg")
        placeholder.innerHTML = "108mg"
      } else if (dosages === "40mg") {
        console.log("Warning! Dose exceeds maximum daily dose.")
        placeholder.innerHTML = "Warning! Dose exceeds maximum daily dose."
      } else if (dosages === "50mg") {
        console.log("Warning! Dose exceeds maximum daily dose.")
        placeholder.innerHTML = "Warning! Dose exceeds maximum daily dose."
      } else if (dosages === "60mg") {
        console.log("Warning! Dose exceeds maximum daily dose.")
        placeholder.innerHTML = "Warning! Dose exceeds maximum daily dose."
      }
    }
    if (toTheseMedications === "Vyvanse") {
      if (dosages === "10mg") {
        console.log("30mg")
        placeholder.innerHTML = "30mg"
      } else if (dosages === "20mg") {
        console.log("50mg")
        placeholder.innerHTML = "50mg"
      } else if (dosages === "30mg") {
        console.log("70mg")
        placeholder.innerHTML = "70mg"
      } else if (dosages === "40mg") {
        console.log("Warning! Dose exceeds maximum daily dose.")
        placeholder.innerHTML = "Warning! Dose exceeds maximum daily dose."
      } else if (dosages === "50mg") {
        console.log("Warning! Dose exceeds maximum daily dose.")
        placeholder.innerHTML = "Warning! Dose exceeds maximum daily dose."
      } else if (dosages === "60mg") {
        console.log("Warning! Dose exceeds maximum daily dose.")
        placeholder.innerHTML = "Warning! Dose exceeds maximum daily dose."
      }
    }
  }
}


function convertConcerta() {
  var convertMedications = document.getElementById("convertMedications").value;
  var dosages = document.getElementById("dosages").value;
  var toTheseMedications = document.getElementById("toTheseMedications").value;
  var placeholder = document.getElementById("placeholder");

  if (convertMedications === "Concerta") {
    if (toTheseMedications === "Ritalin") {
      if (dosages == "18mg") {
        console.log("5mg")
        placeholder.innerHTML = "5mg"
      } else if (dosages == "36mg") {
        console.log("10mg")
        placeholder.innerHTML = "10mg"
      } else if (dosages == "54mg") {
        console.log("15mg")
        placeholder.innerHTML = "15mg"
      }
      if (dosages == "72mg") {
        console.log("20mg")
        placeholder.innerHTML = "20mg"
      }
      if (dosages == "108mg") {
        console.log("30mg")
        placeholder.innerHTML = "30mg"
      }
    }
  }

  if (toTheseMedications === "Ritalin LA") {
    if (dosages == "18mg") {
      console.log("10mg")
      placeholder.innerHTML = "10mg"
    } else if (dosages == "36mg") {
      console.log("20mg")
      placeholder.innerHTML = "20mg"
    } else if (dosages == "54mg") {
      console.log("30mg")
      placeholder.innerHTML = "30mg"
    } else if (dosages == "72mg") {
      console.log("40mg")
      placeholder.innerHTML = "40mg"
    } else if (dosages == "108mg") {
      console.log("50mg")
      placeholder.innerHTML = "50mg"
    }
  }

  if (toTheseMedications === "Dexamfetamine") {
    if (dosages === "18mg") {
      console.log("5mg")
      placeholder.innerHTML = "5mg"
    } else if (dosages === "36mg") {
      console.log("10mg")
      placeholder.innerHTML = "10mg"
    } else if (dosages === "54mg") {
      console.log("15mg")
      placeholder.innerHTML = "15mg"
    } else if (dosages === "72mg") {
      console.log("20mg")
      placeholder.innerHTML = "20mg"
    } else if (dosages === "108mg") {
      console.log("25mg")
      placeholder.innerHTML = "25mg"
    }
  }

  if (toTheseMedications === "Vyvanse") {
    if (dosages === "18mg") {
      console.log("20mg")
      placeholder.innerHTML = "20mg"
    } else if (dosages === "36mg") {
      console.log("30mg")
      placeholder.innerHTML = "30mg"
    } else if (dosages === "54mg") {
      console.log("40mg")
      placeholder.innerHTML = "40mg"
    } else if (dosages === "72mg") {
      console.log("50mg")
      placeholder.innerHTML = "50mg"
    } else if (dosages === "108mg") {
      console.log("70mg")
      placeholder.innerHTML = "70mg"
    }
  }
}

function concvertVyvanse() {
  var convertMedications = document.getElementById("convertMedications").value;
  var dosages = document.getElementById("dosages").value;
  var toTheseMedications = document.getElementById("toTheseMedications").value;
  var placeholder = document.getElementById("placeholder");

  if (convertMedications === "Vyvanse") {
    if (toTheseMedications === "Ritalin") {
      if (dosage === "20mg") {
        console.log("10mg")
      } else if (dosage === "30mg") {
        console.log("15mg")
        placeholder.innerHTML = "15mg"
      } else if (dosage === "40mg") {
        console.log("20mg")
        placeholder.innerHML = "20mg"
      } else if (dosage === "50mg") {
        console.log("25mg")
        placeholder.innerHML = "25mg"
      } else if (dosage === "60mg") {
        console.log("30mg")
        placeholder.innerHML = "30mg"
      } else if (dosage === "70mg") {
        console.log("35mg")
        placeholder.innerHML = "35mg"
      }
    }
  }
}


function init() {

  const button = document.getElementById("button");
  button.addEventListener("click", myFunction);

  function myFunction() {
    if (document.getElementById("convertMedications").value === "Ritalin LA") {
      document.getElementById("button").onclick = convertRitalinLA;
    }
    if (document.getElementById("convertMedications").value === "Ritalin") {
      document.getElementById("button").onclick = convertRitalin;
    }
    if (document.getElementById("convertMedications").value === "Dexamfetamine") {
      document.getElementById("button").onclick = convertDexamfetamine;
    }
    if (document.getElementById("convertMedications").value === "Concerta") {
      document.getElementById("button").onclick = convertConcerta;
    }
    if (document.getElementById("convertMedications").value === "Vyvanse") {
      document.getElementById("button").onclick = convertVyvanse;
    }
  }

}

window.onload = init;
<div id="header">
  <img src="flag.png" alt="Australian flag." width="150" height="75">
  <h1>The Australian ADHD Medication Calculator</h1>
  <p>This calculator will only convert medications that are available for sale in Austraia. Unlike other, US based calculators, you won't have to scroll through a whole list of medications with strange names. Also, you using this calculator means a lot to
    its (Aussie) creator!
  </p>
</div>
<div id="convert">
  <h3>I want to convert...</h3>
  <form id="medications">
    <label for="convertMedications"></label>
    <select name="convertMedications" id="convertMedications">
      <option value="Ritalin">Ritalin</option>
      <option value="Ritalin LA">Ritalin LA</option>
      <option value="Concerta">Concerta</option>
      <option value="Dexamfetamine">Dexamfetamine</option>
      <option value="Vyvanse">Vyvanse</option>
    </select>
    <label for="dosages"></label>
    <select name="dosages" id="dosages">
      <option value="5mg">5mg</option>
      <option value="10mg">10mg</option>
      <option value="18mg">18mg</option>
      <option value="20mg">20mg</option>
      <option value="27mg">27mg</option>
      <option value="30mg">30mg</option>
      <option value="36mg">36mg</option>
      <option value="40mg">40mg</option>
      <option value="50mg">50mg</option>
      <option value="54mg">54mg</option>
      <option value="60mg">60mg</option>
      <option value="70mg">70mg</option>
    </select>
  </form>
</div>
<div id="toThese">
  <h3>to</h3>
  <form>
    <label for="toTheseMedications"></label>
    <select name="toTheseMedications" id="toTheseMedications">
      <option value="Ritalin">Ritalin</option>
      <option value="Ritalin LA">Ritalin LA</option>
      <option value="Concerta">Concerta</option>
      <option value="Dexamfetamine">Dexamfetamine</option>
      <option value="Vyvanse">Vyvanse</option>
    </select>
    <button id="button" type="button" onclick=init()>Convert!</button>
  </form>
  <p id="placeholder"></p>
</div>

bcrypt.compare always returns false when comparing passwords

For some reason bcrypt.compare stopped working and doMatch always returns false. I’m able to create new users with hashed password but then cannot log in for the aforementioned reason. My login controller is:

  const postLoginController = async (req, res) => {
  const email = req.body.email;
  const password = req.body.password;
  try {
    User.findOne({ email: email }).then((user) => {
      console.log('password, user.password', password, user.password);
      bcrypt.compare(password, user.password).then((doMatch) => {
        console.log('doMatch', doMatch);
        //Comparing the password the user entered with the password stored in the db
        if (doMatch) {
          console.log('passwords match');
          req.session.isLoggedIn = true;
          req.session.user = user;
          req.session.save();
          res.status(200).json({ isLoggedIn: true, message: 'Logged in!' });
        } else {
          res
            .status(401)
            .json({ isLoggedIn: false, message: 'Invalid credentials. Please try again.' });
        }
      });
    });
  } catch (err) {
    res.status(400).json({ error: 'Failed to login.' });
  }
};

The console.log returns both the string and the hashed passwords:

password, user.password 123456 $2a$12$9YqCOmycoiLJ8uf7HfL4HebR2hHrJ7b2e6YspG7cP8.6UeAbapHEm

However, as I mentioned, comparing them results in doMatch always being false. Any idea why this is happening? It was working previously. I reinstalled bcryptjs, which is at version 2.4.3 currently, but it didn’t help.