UseNavigate is not working for dynamic search query

useNaviagte() of react-router-dom:^6.7.0 is not working for a dynamic search query. How to use my search text as a navigating route?

My Search component:


import { useNavigate } from 'react-router-dom';

function SearchBar() {
    const [searchItem, setSearchItem] = useState("")
    const navigate = useNavigate();

    const handleSubmit = (e) =>{
        e.prevnetDefault()
        navigate(`/search?q=${searchItem}`)
    };

  return (
    <div className='search-bar'>
        <form onSubmit={handleSubmit}>
            <label htmlFor='search'>Search: </label>
            <input
                type= "text"
                id= "search"
                onChange= {(e) => setSearchItem(e.target.value)}
            />
        </form> 
         ... ...    

In App.js:

{
    path: "/search",
    element: <div><Search/></div>,
  },

Package.json:

"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.7.0",

vanilla Javascript draggable infinite carousel translation problem

so i started an infinite carousel with this principle to limit html dom reflow :
( current code : https://codepen.io/Woots/pen/BaPZegM?editors=0010 )
enter image description here

Gray rectangle is on screen visible part.
In pink the “originals” slides, red the “copy”.
When scroll to the right, it hit the right limit (1) and “leap” to (2).
Same thing when sliding to the left with (3) -> (4)

The illusion is perfect when working with scrollLeft attribute, or translate with no transition ( or 10ms max )
But the movement isn’t smooth…

So i started to use element.animate() which is really great to control animation to have smooth animation with higher duration (100+ )
But now when going from (1) -> (2) or (3) -> (4) its not instant anymore.

By setting a duration: 0 just for the leap its still create a “cut” during movement…
As start -> end js calculation is instant, but transition it take, i.e: 1s, to reach “end value”. (it take the final distance and not the in translation one )
Doing so neither keep the momentum of the transalation..

And that’s where i’am stuck, anyone would have an idea on how to solve that ?

thanks !

Expected an assignment or function call and instead saw an expression in custom hooks

In given custom hook I’m getting error on line cached using useMemoCompare and cleanup function of hook.

import { db } from '../config/firebasse.config'
import {
    collection,
    getDocs
} from 'firebase/firestore';
import { useState, useEffect, useRef } from 'react';
import { useMemoCompare } from "./useMemoComapre";

const compareTwoString = (str1: string, str2: string) => {
    return str1 === str2
}

const useFirebaseGetAll = (
    collectionName: string
) => {
    const [data, setData] = useState([{}]);
    const [type, setType] = useState<"success" | "error" | "loading">("loading");
    const mounted = useRef(false);
    const cached = useMemoCompare(collectionName, compareTwoString);

    useEffect(() => {
        if (cached || mounted.current) {
            return;
        }

        // firebase queries

        return () => {
            mounted.current = true;
        }

    }, []);

    return { type, data, };
}

export default useFirebaseGetAll;

Given below is the implementation of useMemoComapre

import { useEffect, useRef } from "react"

export const useMemoCompare = (value: any, compareFunc?: any) => {
    // learnt from useHooks.com
    const prevRef = useRef();
    const previousValue = prevRef.current;
    let isEqual = false;
    if (compareFunc) isEqual = compareFunc(previousValue, value);

    useEffect(() => {
        if (!isEqual) prevRef.current = value;
    }, [isEqual]);

    return isEqual ? true : false;
}   

Why does my toast notification not re-render in React?

I am trying to create my own “vanilla-React” toast notification and I did manage to make it work however I cannot wrap my head around why one of the solutions that I tried is still not working.

So here we go, onFormSubmit() I want to run the code to get the notification. I excluded a bunch of the code to enhance readability:

const [notifications, setNotifications] = useState<string[]>([]);

const onFormSubmit = (ev: FormEvent<HTMLFormElement>) => {
  ev.preventDefault();

  const newNotifications = notifications;
  newNotifications.push("success");

  console.log(newNotifications);
  setNotifications(newNotifications);
};

return (
  <>
    {notifications.map((state, index) => {
      console.log(index);
      return (
        <ToastNotification state={state} instance={index} key={index} />
      );
    })}
  </>
</section>
);

Inside the Toast I have the following:

const ToastNotification = ({
  state,
  instance,
}: 
{
  state: string;
  instance: number;
}) => {
  const [showComponent, setShowComponent] = useState<boolean>(true);
  const [notificationState, setNotificationState] = useState(
    notificationStates.empty
  );

  console.log("here");

  const doNotShow = () => {
    setShowComponent(false);
  };

  useEffect(() => {
    const keys = Object.keys(notificationStates);

    const index = keys.findIndex((key) => state === key);

    if (index !== -1) {
      const prop = keys[index] as "danger" | "success";
      setNotificationState(notificationStates[prop]);
    }

    console.log(state);
  }, [state, instance]);

  return (
    <div className={`notification ${!showComponent && "display-none"}`}>
      <div
        className={`notification-content ${notificationState.notificationClass}`}
      >
        <p className="notification-content_text"> {notificationState.text} </p>
        <div className="notification-content_close">
          <CloseIcon color={notificationState.closeColor} onClick={doNotShow} />
        </div>
      </div>
    </div>
  );
};

Now for the specific question – I cannot understand why onFormSubmit() I just get a log with the array of strings and nothing happens – it does not even run once – the props get updated with every instance and that should trigger a render, the notifications are held into a state and even more so, should update.

What is wrong with my code?

Unchecked runtime.lastError: Cannot create item with duplicate id highlight-red

I’m trying to create a google chrome extension that will allow me to highlight selected text.

The error I get is: Unchecked runtime.lastError: Cannot create item with duplicate id highlight-red

It’s also not highlighting in any colors.

The JS code:

chrome.contextMenus.create({
  id: "highlight-red",
  title: "Highlight Red",
  contexts: ["selection"]
});

chrome.contextMenus.create({
  id: "highlight-green",
  title: "Highlight Green",
  contexts: ["selection"]
});

chrome.contextMenus.create({
  id: "highlight-blue",
  title: "Highlight Blue",
  contexts: ["selection"]
});



chrome.contextMenus.onClicked.addListener((info, tab) => {
  chrome.scripting.executeScript({
    target: { tabId: tab.id },
    function: setCheck,
    args: [info]
  });
  chrome.scripting.executeScript({
    target: { tabId: tab.id },
    function: highlightSelection,
    args: [info]
  });
});

function setCheck(info) {
  var check = true;
}

function highlightSelection(info) {
  var color = info.menuItemId;
  var selection = window.getSelection().toString();
  var range = window.getSelection().getRangeAt(0);
  var newNode = document.createElement("span");
  newNode.setAttribute("style", "background-color: " + color + ";");
  newNode.appendChild(range.extractContents());
  range.insertNode(newNode);
}

I’m trying to highlight texts

(Chrome Extension) Saving a local file path into storage

I’m creating a Chrome extension which requires the user to insert the local path of a file to access it, which is then saved to storage and retrieved when the user reopens the extension to prevent them from having to re-insert the file path to access it.

I’m currently using Local Storage as the storage method to store these file paths, however security-wise, do you think it would be safe to do this given the low security measures that local storage has, and if not, do you think that something like ‘Indexeddb’ or ‘chrome.storage’ would be better?

Does creating modules in ES6 save memory? Is there any difference in memory allocation for variables, functions from ES5?

Does creating modules in ES6 save memory? Is there any difference in memory allocation for variables, functions from ES5?

Example –
If I have abc.mjs as below

class A
{
    var foo = "foo";
    function doSomething(){
        var bar= "bar";
    }
}
export default A

Now if I import abc.mjs file in some other file, when will foo and bar get in memory?

addEventListener doesn’t work with querySelectorAll and dynamical elements [duplicate]

document.addEventListener('DOMContentLoaded', () => {

    document.querySelectorAll('[id^="delete-btn-"]').forEach(function(button) {
        button.addEventListener('click', function(e) { alert('click') }
    )});
});

The click event is triggered when clicking any buttons already present on the page.
Now if a new button (with a new id) is dynamically added the click event is no longer triggered.

I also tried that way but it doesn’t work either.

let elements = document.querySelectorAll('[id^="delete-btn-"]');
for (let i = 0; i < elements.length; i++) {
    elements[i].addEventListener('click', (e) => {alert('click')});
}

What’s wrong with my code ?

HTML Canvas: CanvasRenderingContext2D transform requires (re)setting canvas size?

I’ve modified
https://codepen.io/chengarda/pen/wRxoyB

A simple example of internally handling scrolling and zooming of canvas contents using mouse and touch events. No JQuery, no libraries, pure JS.

to use a fixed canvas size and replaced the references to window.innerWidth (and Height) accordingly.
The working code resets the canvas size on each draw – removing this causes the code to stop working (current Chrome and Firefox on Ubuntu), and I don’t see why. Does setting the canvas size reset context or what is the (side) effect of doing it?

let canvas = document.getElementById("canvas")
canvas.width = 300;//window.innerWidth
canvas.height = 300;//window.innerHeight
let ctx = canvas.getContext('2d')

let cameraOffset = { x: canvas.width/2, y: canvas.height/2 }
let cameraZoom = 1
let MAX_ZOOM = 5
let MIN_ZOOM = 0.1
let SCROLL_SENSITIVITY = 0.0005

function draw()
{
    //canvas.width = window.innerWidth
    //canvas.height = window.innerHeight
    
    // Translate to the canvas centre before zooming - so you'll always zoom on what you're looking directly at
    ctx.translate( canvas.width / 2, canvas.height / 2 )
    ctx.scale(cameraZoom, cameraZoom)
    ctx.translate( -canvas.width / 2 + cameraOffset.x, -canvas.height / 2 + cameraOffset.y )
    ctx.clearRect(0,0, canvas.width, canvas.height)
    ctx.fillStyle = "#991111"
    drawRect(-50,-50,100,100)
    
    ctx.fillStyle = "#eecc77"
    drawRect(-35,-35,20,20)
    drawRect(15,-35,20,20)
    drawRect(-35,15,70,20)
    
    ctx.fillStyle = "#fff"
    drawText("Simple Pan and Zoom Canvas", -255, -100, 32, "courier")
    
    ctx.rotate(-31*Math.PI / 180)
    ctx.fillStyle = `#${(Math.round(Date.now()/40)%4096).toString(16)}`
    drawText("Now with touch!", -110, 100, 32, "courier")
    
    ctx.fillStyle = "#fff"
    ctx.rotate(31*Math.PI / 180)
    
    drawText("Wow, you found me!", -260, -2000, 48, "courier")
    
    requestAnimationFrame( draw )
}

// Gets the relevant location from a mouse or single touch event
function getEventLocation(e)
{
    if (e.touches && e.touches.length == 1)
    {
        return { x:e.touches[0].clientX, y: e.touches[0].clientY }
    }
    else if (e.clientX && e.clientY)
    {
        return { x: e.clientX, y: e.clientY }        
    }
}

function drawRect(x, y, width, height)
{
    ctx.fillRect( x, y, width, height )
}

function drawText(text, x, y, size, font)
{
    ctx.font = `${size}px ${font}`
    ctx.fillText(text, x, y)
}

let isDragging = false
let dragStart = { x: 0, y: 0 }

function onPointerDown(e)
{
    isDragging = true
    dragStart.x = getEventLocation(e).x/cameraZoom - cameraOffset.x
    dragStart.y = getEventLocation(e).y/cameraZoom - cameraOffset.y
}

function onPointerUp(e)
{
    isDragging = false
    initialPinchDistance = null
    lastZoom = cameraZoom
}

function onPointerMove(e)
{
    if (isDragging)
    {
        cameraOffset.x = getEventLocation(e).x/cameraZoom - dragStart.x
        cameraOffset.y = getEventLocation(e).y/cameraZoom - dragStart.y
    }
}

function handleTouch(e, singleTouchHandler)
{
    if ( e.touches.length == 1 )
    {
        singleTouchHandler(e)
    }
    else if (e.type == "touchmove" && e.touches.length == 2)
    {
        isDragging = false
        handlePinch(e)
    }
}

let initialPinchDistance = null
let lastZoom = cameraZoom

function handlePinch(e)
{
    e.preventDefault()
    
    let touch1 = { x: e.touches[0].clientX, y: e.touches[0].clientY }
    let touch2 = { x: e.touches[1].clientX, y: e.touches[1].clientY }
    
    // This is distance squared, but no need for an expensive sqrt as it's only used in ratio
    let currentDistance = (touch1.x - touch2.x)**2 + (touch1.y - touch2.y)**2
    
    if (initialPinchDistance == null)
    {
        initialPinchDistance = currentDistance
    }
    else
    {
        adjustZoom( null, currentDistance/initialPinchDistance )
    }
}

function adjustZoom(zoomAmount, zoomFactor)
{
    if (!isDragging)
    {
        if (zoomAmount)
        {
            cameraZoom += zoomAmount
        }
        else if (zoomFactor)
        {
            console.log(zoomFactor)
            cameraZoom = zoomFactor*lastZoom
        }
        
        cameraZoom = Math.min( cameraZoom, MAX_ZOOM )
        cameraZoom = Math.max( cameraZoom, MIN_ZOOM )
        
        console.log(zoomAmount)
    }
}

canvas.addEventListener('mousedown', onPointerDown)
canvas.addEventListener('touchstart', (e) => handleTouch(e, onPointerDown))
canvas.addEventListener('mouseup', onPointerUp)
canvas.addEventListener('touchend',  (e) => handleTouch(e, onPointerUp))
canvas.addEventListener('mousemove', onPointerMove)
canvas.addEventListener('touchmove', (e) => handleTouch(e, onPointerMove))
canvas.addEventListener( 'wheel', (e) => adjustZoom(e.deltaY*SCROLL_SENSITIVITY))

// Ready, set, go
draw()
html, body
{
    height: 100%;
    margin: 0;
    padding: 0px;
    overflow: hidden;
}

#canvas
{
 /* width: 100%;
  height: 100%;*/
  background: #111;
}
<canvas id="canvas"></canvas>

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D

keep photo hidden after refreshing page

I have photos with a button to Hide/Show photo. what is needed is as follow:
If I press hide and refresh the page, the photo will remain hidden. I believe that is done by localStorage but I need help.

            int index=0;
            foreach (var item in Model.AttachmentsList)
            {

                <div style=" display: inline-block;">
                    @if (item.FileUrl.Contains(".jpg"))
                    {
                        
                        @Html.Raw("<a href='../../" + item.FileUrl + "' alt='img'> <img id='photo_" + index + "'  src='../../" + item.FileUrl + "'   > </a>")
                    }
                    else
                    {
                        @Html.Raw("<a href='../../" + item.FileUrl + "' target='_blank'>" + item.FileName + "</a>")
                    }
                    
                </div>
                <button onclick="togglePhoto(@index)">Hide/Show Photo</button>
                index++;
            }

here is js:

<script>
function togglePhoto(index) {
    
    var photo = document.getElementById('photo_' + index);
    if (photo.style.display === 'none') {
        photo.style.display = 'block';
        
    } else {
        photo.style.display = 'none';
       
    }
    
}