Using JavaScript Proxy. Render function not getting called with local storage data

Here is my store and all functions working fine for delete , update and add new task.

const store = {
  todos: [
    {
      id: '1',
      title: 'Complete Task A',
      completed: false,
    },
    {
      id: '2',
      title: 'Read Book',
      completed: true,
    },
  ],
};

const storeHandler = {
  get(target, property) {
    return target[property];
  },
  set(target, property, value) {
    target[property] = value;
    if (property == 'todos') {
      window.dispatchEvent(new Event('todoschange'));
    }
    localStorage.setItem('store', JSON.stringify(store));
    return true;
  },
};

const storeProxy = new Proxy(store, storeHandler);

function addTodo(newTodo) {
  console.log(newTodo);
  storeProxy.todos = [...storeProxy.todos, newTodo];
}

function deleteTodo(id) {
  storeProxy.todos = storeProxy.todos.filter((todo) => todo.id !== id);
}
function markAsDone(id, status) {
  storeProxy.todos = storeProxy.todos.map((todo) =>
    todo.id == id ? { ...todo, completed: status } : todo
  );
}

export { addTodo, deleteTodo, markAsDone };
export default store;

Below is code related to app.js.


import render from './render.js';
import { addTodo, deleteTodo, markAsDone } from './store.js';
import store from './store.js';

window.addEventListener('todoschange', () => {
  console.log('todoschange triggered!!!');
  render();
});

// read and write to local storage
const dataFromStorage = JSON.parse(localStorage.getItem('store'));
if (dataFromStorage?.todos.length > 0) {
  console.log(dataFromStorage.todos);
  store.todos = dataFromStorage.todos;
  console.log(store.todos);
} else {
  console.log(store);
  localStorage.setItem('store', JSON.stringify(store));
  render();
}

const form = document.getElementById('form');
const titleField = document.getElementById('todo-title-input');
const todoList = document.querySelector('.todos');

form.addEventListener('submit', (e) => {
  e.preventDefault();
  let todoTitle = titleField.value;
  const newTodo = {
    id: crypto.randomUUID(),
    title: todoTitle,
    completed: false,
  };

  addTodo(newTodo);
  titleField.value = '';
});

todoList.addEventListener('click', (e) => {
  let target = e.target;
  if (target.classList.contains('delete-todo-button')) {
    const id = target.closest('.todo').dataset.id;
    console.log(id);
    deleteTodo(id);
  }

  if (target.classList.contains('todo-checkbox')) {
    const id = target.closest('.todo').dataset.id;
    let status = target.checked;
    console.log(id, status);
    markAsDone(id, status);
  }
});
`

Below is render functions's code 

import store from './store.js';

function render() {
  console.log(store.todos, 'render called');
  const todoElements = store.todos
    .map(
      (todo) => `
  <li class="todo" data-id=${todo.id}>
<span class="todo-title ${todo.completed ? 'completed' : ''}"> ${
        todo.title
      } </span>
<div class="toggle-delete">
  <input type="checkbox" name="completed" class="todo-checkbox" ${
    todo.completed ? 'checked' : ''
  } />
  <button class="delete-todo-button">x</button>
</div>
</li>
  `
    )
    .join('');

  let todoList = document.querySelector('.todos');
  todoList.innerHTML = todoElements;
}

   export default render;

after logging multiple time i noticed that

window.addEventListener('todoschange', () => {
  console.log('todoschange triggered!!!');
  render();
});

this block of code not worked if i have items in local storage and set them into the store. if i clear the local storage then it works fine also on initial render . what’s the problem? please the point out the issue and help me here;

Expected `onClick` listener to be a function, instead got a value of `object` type [closed]

I have this in my app.jsx file

import CoreConcept from './components/CoreConcept.jsx';
import { CORE_CONCEPTS } from './data';
import Header from './components/Header/Header.jsx';
import TabButton from './components/TabButton.jsx';

function App() {
  function handleSelect() {
    console.log('Selected');
}
  return (
    
    <div>
      <Header/>
      <main>
        <section id ="core-concepts">
        <h2>Core Concepts</h2>
        <ul>
          <CoreConcept title = {CORE_CONCEPTS[0].title} 
          description={CORE_CONCEPTS[0].description}
          image={CORE_CONCEPTS[0].image}/>
          <CoreConcept title = {CORE_CONCEPTS[1].title} 
          description={CORE_CONCEPTS[1].description}
          image={CORE_CONCEPTS[1].image}
          />
          <CoreConcept {...CORE_CONCEPTS[2]}/>
          <CoreConcept {...CORE_CONCEPTS[3]}/>
        </ul>
        </section>
        <section id ="examples">
          <h2>Examples</h2>
          <menu>
            <TabButton onSelect = {handleSelect}>Components</TabButton>
            <TabButton onSelect = {handleSelect}>JSX</TabButton>
            <TabButton onSelect = {handleSelect}>Props</TabButton>
            <TabButton onSelect = {handleSelect}>State</TabButton>
          </menu>

        </section>
      </main>
    </div>
  );
}

export default App;

and for my TabButton.jsx file

export default function TabButton(props, onSelect) {
    

    return (
        <li>
            <button onClick={onSelect}>{props.children}</button>
        </li>
    );
}

I have tried fixing the function but dont seem to get hold of the problem, please tell me the appropriate soultion to it. And the handleselect function i have not called it in the tab button

Unable to figure out option filtering in React/ Javascript

Let me give you a little background about my requirement. Based on the value selected from the initial dropdown, that many dropdowns should be generated.I am able to achieve that. I have an array of options-which should be distributed euqally/near equally across the dropdowns. That is not happening. Any thing that I am missing ?

const KPI_OPTIONS = [
    "OEE",
    'Quality',
    'Availabilty',
    'Performance',
    'Good Count',
    'Rejected Count',
    'Ideal Cycle Time',
    'Planned Production Time',
    'Fully Productive Time',
    'Planned Downtime',
    'Unplanned Downtime'
];

const MAX_DROPDOWNS = 4;

const CustomAddModal = ({ open, onClose, createHandler, onOptionsSelected }) => {

    const [selectedDropdownCount, setSelectedDropdownCount] = useState('');
    const [dynamicDropdowns, setDynamicDropdowns] = useState([]);
    const [selectedOptions, setSelectedOptions] = useState(Array.from({ length: MAX_DROPDOWNS }, () => ''));

    console.log(selectedOptions);

    const handleCreate = () => {
        onOptionsSelected(selectedOptions);
        createHandler();
        setSelectedDropdownCount('');
        onClose();
    };

    const generateDynamicDropdowns = (count) => {
        const newDropdowns = Array.from({ length: parseInt(count) }, (_, index) => index + 1);
        setDynamicDropdowns(newDropdowns);
    };

    const handleOptionChange = (index, value) => {
        const newSelectedOptions = [...selectedOptions];
        newSelectedOptions[index] = value;
        setSelectedOptions(newSelectedOptions);
    };

    useEffect(() => {
        generateDynamicDropdowns(selectedDropdownCount);
    }, [selectedDropdownCount]);

    return (
        <Modal
            open={open}
            closeAfterTransition
        >
            <Fade in={open}>
                <div style={{ ...modalStyle, width: '750px' }}>
                    <IconButton style={{ position: 'absolute', top: '10px', right: '10px', color: COLOR_WHITE }} onClick={onClose}>
                        <CloseIcon />
                    </IconButton>
                    <div style={{ color: COLOR_WHITE, textAlign: 'center' }}>Custom</div>
                    <div style={{ color: COLOR_WHITE }}>KPIs</div>
                    <div className="dropdown-container" style={dropdownContainerStyle}>
                        <Select
                            sx={selectStyle}
                            MenuProps={menuProps}
                            value={selectedDropdownCount}
                            onChange={(e) => setSelectedDropdownCount(e.target.value)}
                        >
                            <MenuItem sx={menuItemStyle} value="null">Select Option</MenuItem>
                            <MenuItem sx={menuItemStyle} value="1">1</MenuItem>
                            <MenuItem sx={menuItemStyle} value="2">2</MenuItem>
                            <MenuItem sx={menuItemStyle} value="3">3</MenuItem>
                            <MenuItem sx={menuItemStyle} value="4">4</MenuItem>
                        </Select>
                        {/* Render additional dropdowns based on the dynamicDropdowns array */}
                        {dynamicDropdowns.map((dropdown, index) => (
                            <Select
                                key={index}
                                sx={selectStyle}
                                MenuProps={menuProps}
                                value={selectedOptions[index]}
                                onChange={(e) => handleOptionChange(index, e.target.value)}
                            >
                                <MenuItem sx={menuItemStyle} value="">
                                    Select Option
                                </MenuItem>
                                {KPI_OPTIONS.map((option, optionIndex) => (
                                    <MenuItem key={optionIndex} sx={menuItemStyle} value={option}>
                                        {option}
                                    </MenuItem>
                                ))}
                            </Select>
                        ))}
                    </div>
                    <Button style={buttonStyle} onClick={handleCreate} variant="contained">
                        Create
                    </Button>
                </div>
            </Fade>
        </Modal>
    );
};

How to measure First Screen Paint?

Web Vitals comes with two well known metrics: FCP and LCP. It is good ideas to measure paint time. But I have different problem.

I have to implement a metric which describes when the first screen completely loaded within viewport. It means that I need to measure the least timing when:

either body height larger than viewport height, or document completed

My first attempt to implement this was following:

Sets an interval which checks this condition every 200ms. Pseudo code:

setInterval(() => {
  if (document.body.clientHeight > window.innerHeight || document.readyState === 'complete') {
    resolve(); // commit!
  }
}, 200);

But this way has two major issues:

  1. it’s inaccurate due to 200ms window;
  2. it’s inaccurate due to setInterval does not promise to perform a callback at the specified time.

The second way is to use MutationObserver. Pseudo code:

new MutationObserver(() => {
  if (document.body.clientHeight > window.innerHeight || document.readyState === 'complete') {
    resolve(); // commit!
  }
}).observe(document.body, {attributes: false, childList: true, subtree: true});

It’s fine and solves that issues, but there is a huge problem. In this way need to recalculate window height on each HTML commit. There is a problem for pages with large amount of HTML-chunks which comes from the server.

And this solutions become irrelevant to measure the first screen paint when resources for the first paints and first scripts execution are very important.

My question is how to measure the First Screen Paint metric with minimal performance costs and sufficient accuracy?

Maybe there is an API which I just don’t know about 🙂

position issue with context menu inside scrolled area (floating-ui)

I want to build a context menu on right mouse click and anchor that menu to the clicked position in the scrolled area so that it will not be visible when scroll down. Here is a demo: https://codesandbox.io/p/sandbox/floating-ui-bubble-context-menus-ldyjpy?file=%2Fsrc%2Fcontext-menu.tsx%3A86%2C1

Try to select some text and scroll down – this works properly thanks to contextElement. However, for some reason the same does not work for context menu (on right click). What is the reason?

Should all UI updates be triggered with a pubsub event, or can we manually call a function to trigger an update?

I’ve been working on implementing a chat application where I use the PubSub design pattern to trigger various UI updates. My question is when should we, if at all, manually trigger an update by calling a method directly? We can see two basic examples below. I can manually call dialogs.renderDialogs() within the fetchAllDialogs or updateDialog methods. I’m also not passing anything because the dialogs are accessible on the object level. So it seems a little silly to be to use events to update the UI in this case.

I would love to hear your thoughts! Thanks in advance!

'use strict';

import { pubSub } from './pubsub.js';
import { chatService } from '../services/chatService.js';

export const dialogs = {
  list: [],
  render: (container) => {
    const template = document.getElementById('dialogListTemplate');
    const div = template.content.cloneNode(true);
    container.appendChild(div);

    const dialogList = document.getElementById('dialogsList');
    dialogList.addEventListener('click', dialogs.dialogsChanged);

    pubSub.subscribe('fetchDialogs', dialogs.fetchAllDialogs);
    pubSub.subscribe('messageAdded', dialogs.updateDialog);
    pubSub.subscribe('dialogsUpdated', dialogs.renderDialogs);
    pubSub.subscribe('dialogsFetched', dialogs.renderDialogs);
    pubSub.publish('fetchUsers', null);
  },
  fetchAllDialogs: async () => {
    const data = await chatService.getDialogs();
    dialogs.list = data;
    pubSub.publish('dialogsFetched', null);
    // dialogs.renderDialogs();
  },
  renderDialogs: () => {
    // ...
  },
  dialogsChanged: (evt) => {
    const { userId, username } = evt.target.dataset;
    pubSub.publish('dialogChanged', { userId, username });
  },
  updateDialog: ({ text, sender, recipient, sender_username }) => {
    dialogs.list = dialogs.list.map((dialog) => {
      if (
        dialog.other_user_id === sender ||
        dialog.other_user_id === recipient
      ) {
        return {
          ...dialog,
          last_message: {
            text: text,
          },
        };
      }
      return dialog;
    });
    pubSub.publish("dialogsUpdated", null);
    // dialogs.renderDialogs();
  },
};

Locking past colomons in Google Spreadsheet based on date

I am trying to track a meeting status with some people. This one on one meeting happens every 2 weeks. I wanna make sure that the person can’t update their status after the the two week period passes. So I wanted to write a script that will lock the past colomons and make only the colomons that are still active editable. This is the code I wrote. But I kept getting an error.

function lockPastColumns() {

var sheet = SpreadsheetApp.getActiveSheet();

var headers = sheet.getRange(“A1:H1”).getDisplayValues()[0];

var protection = sheet.protect();
protection.setUnprotectedRanges([sheet.getRange(1, 1, 1, headers.length)]);

var baseDate = new Date();
var today = Utilities.formatDate(baseDate, “GMT”, “yyyy-MM-dd”);

for(var i = 0; i < headers.length; i+=2) {

var date = headers[i];

// Convert to Date object
var headerDate = new Date(date);

// Convert both dates to UTC for comparison
var utcBase = new Date(baseDate.valueOf() + baseDate.getTimezoneOffset()*60000);
var utcHeaderDate = new Date(headerDate.valueOf() + headerDate.getTimezoneOffset()*60000);

if(utcHeaderDate < utcBase){

 // Lock columns
    var startColIndex = i + 1;  
    var endColIndex = i + 2;
    
    protection.setProtectedRanges([sheet.getRange(startColIndex + ":" + endColIndex)]);

}

}
}

function createTrigger() {

ScriptApp.newTrigger(‘lockPastColumns’)
.timeBased()
.everyWeeks(2)
.onWeekDay(ScriptApp.WeekDay.MONDAY)
.create();

}

I am expecting to hear a way to make this without having to use setProtected … kind of functions

why in react we have jsx not jsh?

in react, jsx stands for javascript xml but actually we are trying to use “html” in javascript in react, so why it’s not jsh which stands for javascript html, so I wonder is there any reason behind this naming?

Js is loading but not running in django

I have been creating a website using django but when I try to access a js file in the static folder it doesn’t work. However, in the python terminal I get the following message (meaning that the file is in fact loading but not running):

[21/Jan/2024 10:07:14] “GET /static/CACHE/js/output.10e324644ab8.js HTTP/1.1” 304 0

Also, using the debug_toolbar library which I have added to my project I can see the file is loaded and I can open it.

This is my html code:

<html lang="en">
    <head>
        {% load static %} {% load compress %}
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Centro Psi-Clinico Pisa</title>
        {% compress css %}
        <link
            rel="stylesheet"
            type="text/x-scss"
            href="{% static 'scss/base.scss' %}"
        />
        {% endcompress %}
        <link
            rel="stylesheet"
            href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
            integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw=="
            crossorigin="anonymous"
            referrerpolicy="no-referrer"
        />
        <script src="{% static 'js/main.js' %}"></script>
    </head>
    <body>
        <header>{% include 'navbar.html' %}</header>
        <main>{% block content %} {% endblock %}</main>
    </body>
</html>

How do I use my sign-up form to create a members profile on my website?

I am a complete beginner at coding. Everything i have learned by watching videos and reading things on the internet but i am a very fast learner. I am currently working on creating my own social media website. I have got the design finished. so it looks like a website but now i need to create something that will allow people to sign up to my website. How do i make it so that my sign-up form will collect the data from the new member and check their email and store it so they will be able to log in once they are signed up? also how would i take all their information they put into the sign-up form and use it to set up their profile?

i didnt have a clue i thought i would cross that bridge when it come. and that bridge is here now

function in console.log prints undefined – JavaScript code. Was expecting to print on console what function returns [duplicate]

I am creating function which finds value of key inside JS object. When I run this function I was expecting “data not found” in console log but what I get on console is undefined. Although when inside function instead of return I add console.log there and try printing what I am trying to return it just print it in console.

const data = {
    level1: {
      level2: {
        level3: 'some data'
      }
    }
}



function finData(object,key){
    for (const item in object) {
        if(item===key){
            return object[item]
        }else{
            if(typeof object[item] === 'object'){
                finData(object[item],key)
            }else{
                return "data not found"
            }
        }  
    }
}



console.log(finData(data,'level4'))

Error inserting data: Cannot read properties of undefined (reading ‘execute’)

Inserting a record to a MySQL table after the successful establishment of connection fails. I’m currently stuck with an issue inserting a record into MySQL table although the connection to the DB establishes perfectly. The line that is throwing the error is const [rows] = await connection.execute('SELECT * FROM tracks WHERE isrc = ?', [trackData.isrc]); placed in the JS file mysql-utils.js

index.js contents:

const express = require('express') // Get object of express npm module
const trackSaveRouter = require('./routers/track-save')

const app = express() // Instantiate Express server
const port = process.env.PORT || 4000

app.use(express.json()) // Parse incoming body into JSON
app.use(trackSaveRouter)


app.listen(port, () => {
  console.log('Server is up and running on: ' + port)
})

track-save.js contents

const express = require('express')
const Track = require('../models/track')
const router = new express.Router()
const request = require('request'); // "Request" library
const { connectToMySQL, closeMySQLConnection } = require('../db/mysql-connection')
const { insertData } = require('../utils/mysql-utils');

router.post('/track/save', async (req,res) => { // Route handler
  try {
    // Connect to MySQL
    await connectToMySQL();

    const isrc = req.body.isrc   // Retrieve isrc
    console.log('isrc:', isrc)
    const clientID = 'Hidden' // Your client id
    const clientSecret = 'Hidden' // Your secret

    var authOptions = { // Application requests authorization
      url: 'https://accounts.spotify.com/api/token',
      headers: {
        'Authorization': 'Basic ' + (new Buffer.from(clientID + ':' + clientSecret).toString('base64'))
      },
      form: {
        grant_type: 'client_credentials'
      },
      json: true
    };

    request.post(authOptions, async function (error, response, body) {
      if (!error && response.statusCode === 200) {
        // use the access token to access the Spotify Web API
        var token = body.access_token;
        var options = { // USVT10300001, USEE10001992, GBAYE0601498, USWB11403680, GBAYE0601477
          url: 'https://api.spotify.com/v1/search?q=isrc:' + isrc + '&type=track',
          headers: {
            'Authorization': 'Bearer ' + token
          },
          json: true
        };
        request.get(options, async function (error, response, body) {
          if (error) {
            console.log('Unable to fetch Track data!')
            return
          }

          if (!body.tracks.items || body.tracks.items.length === 0) { 
            console.log('Track data unavailable for ISRC: !' + isrc)
            return
          }

          //console.log(body.tracks.items)
          //process.exit() 
          let musicTrack, trackWithHighPopularity, spotifyImageUri, title, artistNames = [] // In case multiple tracks are returned
          body.tracks.items.forEach((e, index) => {
            //console.log(e.popularity)
            if (index === 0) {
              trackWithHighPopularity = e
              return
            }
            // From second iteration onwards
            if (e.popularity > trackWithHighPopularity.popularity) {
              trackWithHighPopularity = e
            }
          })

          musicTrack = trackWithHighPopularity
          //console.log(musicTrack.album.images)
          //process.exit();
          spotifyImageUri = musicTrack.album.images[0].url // Get spotify image URI
          // console.log(spotifyImageUri)
          title = musicTrack.name // Get Title
          // console.log(title)
          //console.log(musicTrack.artists)
          musicTrack.album.artists.forEach((e)=>{
            artistNames.push(e.name)
          })
          // Convert array into a comma-separated string.
          artistNamesString = artistNames.join(', ')
          //console.log(artistNamesString)
          // Call the insertData function with the trackData parameter
          await insertData({ // Write metadata to DB
            isrc,
            title,
            artistNamesString,
            spotifyImageUri
          })

          console.log('Data inserted successfully');

          // Close MySQL connection after inserting Data
          await closeMySQLConnection();
        });
      }
    });
  } catch (error) {
    console.error('Error processing track:', error);
    res.status(500).send('Internal Server Error');
  }
})

module.exports = router

mysql-connection.js

const mysql = require('mysql2/promise'); // Using promise-based version

const dbConfig = {
  host: 'localhost',
  user: 'root',
  password: '',
  database: 'spotify_web_server_api',
};

let connection;

async function connectToMySQL() {
  try {
    connection = await mysql.createConnection(dbConfig);
    if (connection) {
      console.log('Connected to MySQL');
    }
  } catch (error) {
    console.error('Error connecting to MySQL:', error.message);
  }
}

async function closeMySQLConnection() {
  try {
    if (connection) {
      await connection.end();
      console.log('Closed MySQL connection');
    }
  } catch (error) {
    console.error('Error closing MySQL connection:', error.message);
  }
}

module.exports = { connection, connectToMySQL, closeMySQLConnection };

mysql-utils.js contents

const { connection } = require('../db/mysql-connection');

async function insertData(trackData) {
  try {
    // Check if a record with the given 'isrc' value already exists
    const [rows] = await connection.execute('SELECT * FROM tracks WHERE isrc = ?', [trackData.isrc]);

    if (rows.length > 0) {
      // If a matching record is found, return an error
      throw new Error('Record with the same isrc ' + trackData.isrc + ' already exists');
    }

    // If no matching record is found, insert the data
    await connection.execute('INSERT INTO tracks SET ?', trackData);

    console.log('Data inserted successfully');
  } catch (error) {
    console.error('Error inserting data:', error.message);
  }
}

module.exports = { insertData };

Here are the steps to reproduce the issue if you have credentials for a Spotify developer account.

  1. Run the Express server by running “node index.js”

  2. Run your MySQL server

  3. In your postman app, enter the endpoint http://localhost:4000/track/save, by passing the JSON parameter
    {
    “isrc”:”GBAYE0601477″
    }

  4. In the CLI, you should see the error saying “Error inserting data: Cannot read properties of undefined (reading ‘execute’)”

I tried to pass connection object when calling insertData(), but that still gave the same error. Tried to change let to var. That also didn’t help

Undefined error, when I switch the order of .then statements in my fetch call

“app.js:7 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘map’)”

Error happens here

fetch(NpsImages)
    .then(response=>response.json())
    .then(data => data.data.map(data => generateOptions(data)))
    .then(data => data.data.map(console.log(data)))  // **<<error happens here**

It works when I have .then statement in the order below
-but I need the generateOptions line to run first, since its a dropdown menu with JSON Data for the select options

fetch(NpsImages)
    .then(response=>response.json())
    .then(data => data.data.map(console.log(data)))
    .then(data => data.data.map(data => generateOptions(data)))

rest of code

const selectMenu = document.querySelector("#option-select");
const NpsImages = "https://developer.nps.gov/api/v1/multimedia/galleries";

fetch(NpsImages)
    .then(response=>response.json())
    .then(data => data.data.map(data => generateOptions(data)))
    .then(data => data.data.map(console.log(data)))


// generates select options in a drop down menu from JSON Data
const generateOptions = (data)=>{
    const options = `<option value="${data["title"]}">${data["title"]}</option>`;
    selectMenu.insertAdjacentHTML("afterend", options);
    return options;
}

//generates images from the JSON data called
const generateImages = (data)=>{
    const card = document.querySelector("#card");
    const images = `<img src=${data["images"]["url"]} title='${data["images"]["altText"]}'`;
    card.insertAdjacentHTML("afterend", images);
    return images;
}

To have the console output the data from the JSON data, so I can have images generate when I make a selection from the drop down menu based off of which value is selected.