Why does input.onChange() in my form triggers AsyncValidation Error?

This is my search.jsx Component

const Search = ({
    input,
    isFetching,
    isSelected,
    message,
    options,
    handleSearch,
    handleChange,
    handleSave,
    handleCancel,
}) => (
    <Container>
        <StyledDropdown
            fluid
            selection
            placeholder="Search Name/Email"
            onChange={handleChange}
            onSearchChange={handleSearch}
            options={options}
            search={options => options}
            loading={isFetching}
            noResultsMessage={message}
            selectOnNavigation={false}
        />
        <Buttons>
            <Button type="button" content="Save" primary onClick={handleSave} disabled={!isSelected} />
            <Button type="button" content="Cancel" onClick={handleCancel} />
        </Buttons>
    </Container>
);```

This is my search container, The form throws an error[![enter image description here](https://i.sstatic.net/Z1HkAOmS.png)](https://i.sstatic.net/Z1HkAOmS.png)everytime I click Save and the HandleSave Function is triggered.

This is the handleSave method in the search.jsx container. The form Works fine if I remove the input.onChange() (but author_id is not added to the request payload since I removed that part, Obviously!)


handleSave = () => {
this.props.input.onChange(this.state.value); //-> throws function passed to reduxForm must return a promise
this.props.setSelected(this.getSelectedData());
this.props.toggleEditMode();
}“`

this is the parent container (author_selector.jsx) where search.jsx is called. Even here the input.onChange throws the same error!

class AuthorSelectorContainer extends Component {

    static propTypes = {
        isEditing: bool.isRequired,
        fetchAuthor: func.isRequired,
        setSelected: func.isRequired,
        ...
    };

    componentDidMount() {
        const {
            meta, input, fetchAuthor, setSelected, defaultUserData,
        } = this.props;

        if (meta.initial) {
            fetchAuthor(meta.initial);
        } else {
            setSelected(defaultUserData);
            //input.onChange(defaultUserData.id);  //-> throws function passed to reduxForm must return a promise
             
        }
    }

    render() {
        const { meta: { initial }, selected, isEditing } = this.props;
        const readOnly = (initial !== undefined);

        if (isEditing) {
            return <Search {...this.props} />;
        } else if (selected) {
            return <AuthorSelectorForm {...this.props} readOnly={readOnly} />;
        }
        return null;
    }
}


const mapStateToProps = state => ({
    selected: getSelected(state),
    isEditing: isEditing(state),
    defaultUserData: getUserData(state),
});

This is my middleware.js ( I can’t see why validation is triggered)

const apiMiddleware = store => next => async (action) => {
    const { type, payload } = action;
    const { getState, dispatch } = store;



    if (!type.startsWith('API/')) {
        return next(action);
    }

    const state = getState();
    const access_token = getToken(state);

    if (access_token && payload.url !== '/oauth/token') {
        payload.params = { access_token, ...payload.params };
    }

    const config = {
        baseURL: getBaseURL(state),
        ...payload,
    };

    // pass action to next middlewear. mostly for showing the dispatch on devTool
    next(action);

    try {
        const res = await axios(config);
        return res;

    } catch (error) {
        if (error.response) {
            if (error.response.status === 401) {
                // Unauthorized
                logout()(dispatch);
                dispatch(ui.flash.warn({ header: 'Login Expired', content: 'Please login again' }));
            }
        } else if (error.request) {
            dispatch(ui.flash.error({ header: 'Network Failure', content: 'API server not available' }));
        } else {
            // Something happened in setting up the request that triggered an Error
            dispatch(ui.flash.error({ header: 'Error', content: error.message }));
        }

        throw error;
    }
};

I have tried directly updating state without invoking reduxForm (which has some other issues!).

I have also tried bypassing validation which doesn’t work.

const AuthorSelectorForm = reduxForm({
    form: 'authorSelectorForm',
    validate: undefined,
    asyncValidate: undefined,
})(AuthorSelector);

I want to understand how input.onChange() can trigger async Validation error. How should I got about debugging this issue. Thank you for taking a look!

How can I trigger re-render of an element (which uses state) in a callback function?

I am currently using React (TSX) and have run into a problem regarding states. I am fairly new to this topic so I apologize if this is blatantly obvious to fix..

Consider a callback function testComponent, which, when a button is pressed, renders a new component each time.

Within this component, there will be a select tag and an input tag, and based on what is selected, the input tag must also update.

The select tag will display the name of the object, and the input tag will display its ID, for example.

And, all of the selectedOptions will start off with a default value of options[0] which happens in a useEffect.

This is a recreation of my problem just using the word test instead so that its easier to understand (less context needed). The idea is that every time the select element changes, it should also update the input tag.

export default function CreateTestComponent() {
  const options: any[] = [
    {
      id: 1,
      name: "Test 1"
    },
    {
      id: 2,
      name: "Test 2",
    },
    {
      id: 3,
      name: "Test 3"
    }
  ]
  const [selectedOptions, setSelectedOptions] = useState<any[]>([options[0]]);
  const [testComponentIndex, setTestComponentIndex] = useState<number>(0);
  const [components, setComponents] = useState<any[]>([]);

  useEffect(() => {
    setComponents([testComponent(0)]);
    setTestComponentIndex((old) => old + 1);

    for (let i = 0; i < options.length; i++) {
      setSelectedOptions((old) => {
        const temp = [...old];
        temp[i] = options[0];
        return temp
      })
    }
  }, [])


  const testComponent = (index: number) => {

    return (
      <div className="flex flex-row gap-5" id={`${index}`}>
        <select
          onChange={((e) => {
            const id = e.target.value;
            setSelectedOptions((old) => {
              const temp = [...old]
              temp[index] = options.filter((option) => option.id == id)[0];
              return temp;
            })
          })}>
          {options.map((option, index: number) => {
            return (
              <option key={index} value={option.id}>
                {option.name}
              </option>
            );
          })}
        </select>
        <input readOnly value={selectedOptions[index].id} />
      </div>
    )
  }

  return (
    <>
      <button type="button" onClick={() => {
        setTestComponentIndex((old) => old + 1)
        setComponents([...components, testComponent(testComponentIndex)]);
      }} className="bg-black text-white rounded px-3 py-1">
        Add a Component
      </button>
      <div>
        <h1>Component testing!</h1>
        <div>
          <ul className="list-none">
            {components.map((component: any, index: number) => {
              return (
                <li key={index}>
                  <div className="flex flex-row gap-5">
                    {component}
                  </div>
                </li>
              )
            })}
          </ul>
        </div>
      </div>
    </>
  )
}

This code will work in a .tsx file.

As you can see, the state is updating, but the input tag doesn’t update. I have done an annoying amount of research trying to figure out what is happening, and I am pretty sure that because it is inside a callback function in which the state is not continuously updated (which would, in turn, trigger a rerender).

I tried doing a bunch of things to get around this obstacle. Namely, I tried useRef(), but it doesn’t have the capability of rerendering, which only useState appears to do.

I went through a bunch of other things but none of them got around this problem because none of them combatted the problem that is that the state is not the same outside versus inside the callback function.

If there is no way around having an up-to-date state within a callback function, what are some other alternatives I could try so that I could still have the ability of pressing a button and generating a new instance of a component each time?

Thanks

Infinite Scrolling PAGE AND LIMIT

Asking about the _page=${page}&_limit=${PAGE_SIZE + 1} when trying to use my own API or JSON FILE

  const fetch = async () => {
    axios
      .get(
        `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=${
          PAGE_SIZE + 1
        }`
      )
      .then((response) => {
        const data = response.data;
        const items = response.data.slice(0, 8);

        setHasMore(data.length > PAGE_SIZE);
        if (posts.length === 0) {
          setPosts(items);
        } else {
          setPosts((v) => [...v, ...items]);
        }
      })
      .finally(() => {
        if (!bootstrapped) {
          setBootstrapped(true);
        }
      });
  };`

App content vertically centered, BUT WHY?

I’m working on a React application where I have a fixed header at the top of the page. Below the header, I have a content area that should start immediately after the header. However, the content appears to be vertically centered within the viewport, and I’m not sure why.

When resizing the browser window the content is displayed from the top, as it should.

So it kinda works but also not?

This is my relevant .js and .css:

.js:

import React, { useState, useEffect, useRef } from 'react';
import { Link } from 'react-router-dom';

const BrowseAll = () => {
    const [posts, setPosts] = useState([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    const scrollContainerRef = useRef(null);

    useEffect(() => {
        fetchAllPosts();
    }, []);

    useEffect(() => {
        const updateBodyHeight = () => {
            if (scrollContainerRef.current) {
                scrollContainerRef.current.style.height = `${window.innerHeight}px`;
            }
        };

        window.addEventListener('resize', updateBodyHeight);
        updateBodyHeight();

        return () => {
            window.removeEventListener('resize', updateBodyHeight);
        };
    }, []);

<----- some more code here inbetween ----->

    return (
        <div className="browse-all" ref={scrollContainerRef}>
            <h1>All Posts</h1>
            {posts.map(post => (
                <div key={post._id} className="post bg-gray-800 text-white rounded-lg p-4 mb-4 w-full max-w-2xl">
                    <h2 className="text-2xl font-semibold">{post.title}</h2>
                    <p className="mb-2">{post.content}</p>
                    <p className="mb-2">Posted on: {new Date(post.created_at).toLocaleString()}</p>
                    <Link to={`/post/${post._id}`} className="mt-4 inline-block text-center bg-blue-500 text-white py-2 px-4 rounded">
                        View Post Details
                    </Link>
                </div>
            ))}
        </div>
    );
};

.css:

.browse-all {
    min-height: 100vh;
    margin-top: 60px;
    padding: 20px;
    max-width: 800px;
    margin: 0 auto;
}

.browse-all body {
    overflow: auto;
}

.browse-all h1 {
    text-align: center;
    margin-bottom: 20px;
}

.browse-all .post {
    background-color: #2a2a2a;
    border: 1px solid #3a3a3a;
    border-radius: 8px;
    margin-bottom: 20px;
    padding: 20px;
    align-items: left;
    text-align: left;
}

.browse-all .post h2 {
    margin-top: 0;
}

.browse-all .comments {
    margin-top: 10px;
}

.browse-all .comment {
    background-color: #3a3a3a;
    border-radius: 5px;
    padding: 10px;
    margin-top: 10px;
}

I tried removing the scrollContainerRef, the useEffect hook that sets the height and playing around with the CSS. No luck.

how to render a specific piece of data from Mysql database to my front end html using Js and node

so i am building a note system and how i have it setup is that on the home page it gives you a preview of the note and if you want to see the whole note you click on it and it pulls up a modal pop-up and would display the full note. im having trouble building my fetch request to get the specified note and then render it into the modal. any suggestions would very appreciated

iv tried just building a basic fetch request but i can only really find examples of POST requests or generic GETs that would just all my notes, not a specific one.

<div id="noteDisplay" class="noteDisplay">
<ul>
    <% note.forEach(note =>{ %>

    
    <li>
        <p><%= note.title%></p>
    </li>
    <li>
        <p><%= note.body.substring(0, 250)  %> <span class="noteViewModalBtn" id=<%= note.NoteId %>>...</span></p>
    </li>
    <% }) %>
</ul>

×

<div class="noteViewModalContent">

    
</div> 
    document.querySelectorAll('.noteViewModalBtn').forEach(item => {
item.addEventListener('click', event => {
//handle click
    fetch("http://localhost:8080/note")
    .then()
noteViewModal.style.display = "flex";
})

})

app.get("/note", checkNotAuthenticated, async(req, res) =>{  

const note = await getNote(id)
res.send(note)

})

 async function getNote(id){
const [rows] = await pool.query(`
    SELECT *
    FROM userNotes
    Where NoteId = ?
    `, [id])
    return rows

}

Very odd useEffect react nextjs issue

I have an odd issue I am dealing with. I have this useEffect function which is supposed to run on my program’s start to check that they are logged in, and generate a dynamic element, named lists. Code is below:

// Initial Effect: Fetch access and lists data on component mount
useEffect(() => {
    console.log('Running on launch!')
    getAccess();
    getLists();
}, []);

I am expecting this to run getLists() everytime the page is loaded. This is because our users can interact with the lists — they can add items to it and delete items (which updates our Postgres backend). I always want to dynamically pull the latest version of lists.

The function and route are shown below.

// Fetch list data from the server
const getLists = async () => {
    const data = await fetch("/api/prospects/getLists/");
    const json_data = await data.json();
    console.log(json_data);
    setLists([...json_data]);
};
"use server";

import * as db from "../../../../lib/db"
import { NextRequest, NextResponse } from 'next/server';

export async function GET(req: NextRequest) {
    const list = await db.query(`
    SELECT id, name FROM "List"
    ORDER BY name ASC
    `, []);
    
    return NextResponse.json(list.rows);
}

However, let’s say I add an element to the list and then refresh my page. I can verify the useEffect function is being called as I see “Running on launch!” executed in my console. However, the console.log where we log the json_data will ALWAYS show the original state of the list table. If I start the program with 5 elements in list, and add a sixth, no matter how many times I refresh the page, it is showing me that my route is only returning the original 5 elements. Same issue with deletion. It never gets updated.

Importantly, I confirmed that my postgres table is indeed taking the changes in real time. So it isn’t an issue with adding or deletion.

How do I fix it so it dynamically always pulls the latest version of the List table on refresh?

It should also be important to note it works correctly in my development environment, but if I build it using npm run build on my local machine, or push it to github to my live version on vercel, then this issue happens.

dnd kit nested button does not register onClick

I have a button nested in a sortable list using dnd kit and core UI, however when I click on a button, the onClick function does not event get called.

const [pIndex, setPeopleIndex] = useState(0)

const handleClick = (peopleIndex) => {
  console.log(peopleIndex) //This is being all passed in as `0` by <ListItemComponent /> 
}


{
  data.people.map((element, peopleIndex) => (
    <div key={peopleIndex}>
      <AccordianHeaderComponent onClick={() => setPeopleIndex(peopleIndex)} />
      <DndContext
        sensors={sensors}
        collisionDetection={closestCenter}
        onDragEnd={handleDragEnd}
      >
         <SortableContext
           items={element.addresses}
           strategy={verticalListSortingStrategy}
         >
           {
             element.addresses.map((address, addressIndex) => (
                <ListItemComponent 
                  key={addressIndex} 
                  handleClick={handleClick}
                  peopleIndex={peopleIndex}
                />
             ))
           }
        </SortableContext>
     </DndContext>
   </div>
 ))
}
const ListItemComponent = ({handleClick, peopleIndex}) => {
    const {
    attributes,
    isDragging,
    listeners,
    setNodeRef,
    transform,
    transition,
  } = useSortable({ id: dragID });

  return (<li 
           onClick{openModal}
           id={dragID}
           ref={setNodeRef}
           style={style}
           {...attributes}
           {...listeners}
          >
           <MenuDropDown openModal={openModal} />
          </li>
        )
}
// MenuDropDown Component

const MenuDropDown  = ({openModal}) => {

  const handleMenuItemClick = () => openModal()

  return (
   <CDropDown>
     <CDropdownToggle className="bg-white border-none" caret={false}>
       <CIcon icon={cilOptions} size="lg" />
     </CDropdownToggle>
     <CDropdownMenu>
       <CDropdownItem onClick={handleMenuItemClick}>Edit Question</CDropdownItem>
     </CDropdownMenu>
   </CDropDown>
  )
}

For some reason, when clicking on MenuDropDown which should show a drop down menu, is not working after adding dnd kit to the list of items

How to remove ‘hidden’ class [closed]

I am having trouble removing the ‘hidden’ class on my inputPlaceholder. I checked the console, and the hidden class remains after clicking the “allClearBtn.”

Here is my code:

const resultBox = document.querySelector("#result");
const inputPlaceholder = document.querySelector('.result-span')
function clearInput() {
  inputPlaceholder.classList.remove('hidden',);
}
numberBtns.forEach(function (number){
  number.addEventListener("click", function(){
    inputPlaceholder.classList.add('hidden');
    resultBox.innerHTML += number.innerHTML;
  });
});

I tried using classList.replace(), using a visible class which set my inputPlaceholder to “display:block”, but that did not work. I also made sure my clearInput function was being triggered by doing resultBox.textContent = ”, which did work.

How to get selected text in JavaScript as a string while including alt text from images using document.getSelection()?

I’m trying to write a function that triggers when the user copies text, the function should add the selected text to the clipboard minus any blank lines. Consider the following HTML:

<html>
Blah blah
<br><br>
<img src="https://en.wikipedia.org/static/images/icons/wikipedia.png" alt="alt" />
<br><br>
blah blah
</html>

This gives the following result when copying the entire page:

Blah blah

alt

blah blah

Great, now I just need to intercept the copy event and remove the blank lines. Add the following script to the above example:

<script>
document.addEventListener('copy', (event) => {
    var selectedText = document.getSelection().toString();
    //Code to remove blank lines will go here
    event.clipboardData.setData('text/plain', selectedText);
    event.preventDefault();
});
</script>

But now when you copy the entire page you get the following result:

Blah blah



blah blah

It skips the alt text of the image for some reason, now it replaces it with another blank line. Why?

My first thought is that toString() is somehow removing it, which would be very problematic since I need that to manipulate the copied text, but if I don’t include toString() I get the same result.

Why is document.getSelection() giving me a different result than when I copy the page without it?

‘_Map’ is not a subtype of type ‘String’

i am getting this error “_Map<String, dynamic>’ is not a subtype of type ‘String” while trying to use provider and i confused where the error is have a look my model

// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:convert';

class User {
  final String id;
  final String name;
  final String email;
  final int phone;
  final String? image;
  final String location;
  final String sex;
  final String password;
  final String? age;
  final String? preferredLocation;
  final List<dynamic>? education;
  final List<dynamic>? workExperience;
  final String role;
  final List<dynamic>? applications;
  final List<dynamic>? favoriteJobs;
  User({
    required this.id,
    required this.name,
    required this.email,
    required this.phone,
    this.image,
    required this.location,
    required this.sex,
    required this.password,
    this.age,
    this.preferredLocation,
    this.education,
    this.workExperience,
    required this.role,
    this.applications,
    this.favoriteJobs,
  });

  Map<String, dynamic> toMap() {
    return <String, dynamic>{
      'id': id,
      'name': name,
      'email': email,
      'phone': phone,
      'image': image,
      'location': location,
      'sex': sex,
      'password': password,
      'age': age,
      'preferredLocation': preferredLocation,
      'education': education,
      'workExperience': workExperience,
      'role': role,
      'applications': applications,
      'favoriteJobs': favoriteJobs,
    };
  }

  factory User.fromMap(Map<String, dynamic> map) {
    return User(
      id: map['_id'] ?? "",
      name: map['name'] ?? "",
      email: map['email'] ?? "",
      phone: map['phone'] ?? 0,
      image: map['image'] ?? "",
      location: map['location'] ?? "",
      sex: map['sex'] ?? "",
      password: map['password'] ?? "",
      age: map['age'] ?? "",
      preferredLocation: map['preferredLocation'] ?? "",
      education: map['education'] != null
          ? List<Map<String, dynamic>>.from(
              (map['education']?.map((x) => Map<String, dynamic>.from(x))))
          : [],
      workExperience: map['workExperience'] != null
          ? List<Map<String, dynamic>>.from(
              (map['workExperience']?.map((x) => Map<String, dynamic>.from(x))))
          : [],
      role: map['role'] ?? "job_seeker",
      applications: map['applications'] != null
          ? List<Map<String, dynamic>>.from(
              (map['applications']?.map((x) => Map<String, dynamic>.from(x))))
          : [],
      favoriteJobs: map['favoriteJobs'] != null
          ? List<Map<String, dynamic>>.from(
              (map['favoriteJobs']?.map((x) => Map<String, dynamic>.from(x))))
          : [],
    );
  }

  String toJson() => json.encode(toMap());

  factory User.fromJson(String source) =>
      User.fromMap(json.decode(source) as Map<String, dynamic>);
}

and my provider is looking like this

import 'package:flutter/material.dart';
import 'package:job_finder_app/models/usermodel.dart';

class AllusersProvider extends ChangeNotifier {
  List<User> _users = [];

  List<User> get users => _users;


`  void setUsers(List<User> users) {
`    _users = users;
    notifyListeners();
  }

  void addUser(User user) {
    _users.add(user);
    notifyListeners();
  }

  void removeUser(User user) {
    _users.remove(user);
    notifyListeners();
  }

}

i printed the response and i am getting my responses as json and it looks the data but i cant use it in Ui becaouse i am geting _Map<String, dynamic>’ is not a subtype of type ‘String this error

React: Reading map from local storage returns null values

I am making a small game website where users choose between “easy, medium, and hard” difficulties and I am using a hook of type map to keep track of the guess count for each difficulty. I got it to work normally, but the problem is I want to save user’s guesses so if they come back the website will remember where they were at in the game similar to games like Wordle. However, the code below returns undefined if localstorage is empty when it should be returning 6 as shown below.

const Demo = () =>
{
    const [guessCount, setGuessCount] = useState(new Map()); // Key: [difficulty, count]

    const updateGuessCount = (key: string, value: any) =>
    {
        setGuessCount(map => new Map(map.set(key, value)));
    }

    useEffect(() => 
    {
        updateGuessCount("easy",  localStorage.getItem("easyGuessCount") || 6);
        updateGuessCount("medium", localStorage.getItem("mediumGuessCount") || 6);
        updateGuessCount("hard", localStorage.getItem("hardGuessCount") || 6);

    }, []);

    useEffect(() => 
    {
        localStorage.setItem("easyGuessCount", guessCount.get("easy"));
        localStorage.setItem("mediumGuessCount", guessCount.get("medium"));
        localStorage.setItem("hardGuessCount", guessCount.get("hard"));

    }, [guessCount]);
}

I expected for all the values to be 6 if there is localstorage is empty, but it instead returns undefined. The asynchronous behavior of useEffect() has been making this difficult to debug.

How to activate first menu item on dropdown click in Bootstrap 5

Bootstrap 5 dropdown is defined as

<div class="btn-group">
  <button type="button" class="btn btn-danger dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
    Action
  </button>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item" href="#"><u>A</u>ction</a></li>
    <li><a class="dropdown-item" href="#">A<u>n</u>other action</a></li>
    <li><a class="dropdown-item" href="#"><u>S</u>omething else here</a></li>
    <li><hr class="dropdown-divider"></li>
    <li><a class="dropdown-item" href="#">S<u>e</u>parated link</a></li>
  </ul>
</div>

https://jsfiddle.net/b6or2s5e/

If clicked in Action button, first menu item Action is not active (highlighted):

enter image description here

Pressing down arrow is required to activate it:

enter image description here

How to fix it so that opening dropdown highlights first item like in normal windows desktop application menus?

Iframe Youtube API doesn’t work in android webview

I have custom JS player based on IFrame Youtube API. And this player works everywhere except of WebView on Android.
For debugging I connected Android Smartphone to laptop and checked console in Chrome on this page: chrome://inspect/#devices.

In console I see these errors:

Uncaught TypeError: s.playVideo is not a function
at HTMLDivElement. (player.js:1:3594)

Uncaught ReferenceError: _yt_player is not defined
at embed.js:292:104

Uncaught ReferenceError: await is not defined
at :1:13

Uncaught TypeError: p.playVideo is not a function
at HTMLButtonElement.

Looks like API doesn’t init.
My script player.js connected to the page as file. Also tried to connect iframe api as file before my file but situation is the same.

What can be wrong? Part of my player.js file below:

document.addEventListener('DOMContentLoaded', function() {
    var players = [];

    var tag = document.createElement('script');

    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    // This function is called when the YouTube IFrame API is ready
    function onYouTubeIframeAPIReady() {
        document.querySelectorAll('.player__container').forEach((container, index) => {
            var videoId = container.dataset.id;
            var playerElement = container.querySelector('.player');
            var coverElement = container.querySelector('.player__cover');

            // Set cover image from YouTube thumbnail
            coverElement.style.backgroundImage = `url(https://img.youtube.com/vi/${videoId}/maxresdefault.jpg)`;

            // Initialize the YouTube player
            var player = new YT.Player(playerElement, {
                width: "590",
                height: "640",
                videoId: videoId,
                playerVars: {
                    controls: 0,
                    disablekb: 0,
                    modestbranding: 1,
                    rel: 0,
                    autohide: 1,
                    showinfo: 0,
                    playsinline: 1
                },
                events: {
                    'onReady': (event) => {
                        onPlayerReady(event, container, player, videoId);
                    },
                    'onStateChange': onPlayerStateChange
                }
            });

            // Store the player instance
            players.push(player);
        });
    }

    // This function is called when the player is ready
    function onPlayerReady(event, container, player, videoId) {
        // Setup controls and cover only after player is ready
        setupControls(container, player);
        setupCover(container.querySelector('.player__cover'), player);
    }

    // Handle player state changes (currently empty)
    function onPlayerStateChange(event) {
    }

    // Setup controls for play, pause, stop, volume, etc.
    function setupControls(container, player) {
        var playButton = container.querySelector('.player__play');
        var coverElement = container.querySelector('.player__cover');
        // Another controls...

        // Play button event
        playButton.addEventListener('click', () => {
            player.playVideo();
            coverElement.classList.add('hidden');
        });

        // Another button events...
    }

    // Setup cover click event to play video
    function setupCover(coverElement, player) {
        coverElement.addEventListener('click', () => {
            coverElement.classList.add('hidden');
            player.playVideo();
        });
    }

    // Assign the onYouTubeIframeAPIReady function to the global window object
    window.onYouTubeIframeAPIReady = onYouTubeIframeAPIReady;
});

ERR_REQUIRE_ESM on node.js app – only on web host and not on local server

I’m trying to implement this Google Wallet pass converter (https://github.com/google-wallet/pass-converter) on my website as a node.js app. I have it working locally on my computer running a local WordPress installation with npm version 10.3.0, node.js 20.11.0, PHP 7.4.30, and an Apache web server.

When I install the app through cPanel on my host using the node.js web app installation, after running npm install and trying node app.js demo I receive the following error:

.../public_html/wp-content/plugins/tickera-wallet-passes/pass-converter/config.js:17
const stripJsonComments = require('strip-json-comments');
                          ^

Error [ERR_REQUIRE_ESM]: require() of ES Module /public_html/wp-content/plugins/tickera-wallet-passes/pass-converter/node_modules/strip-json-comments/index.js from /public_html/wp-content/plugins/tickera-wallet-passes/pass-converter/config.js not supported.
Instead change the require of index.js in /public_html/wp-content/plugins/tickera-wallet-passes/pass-converter/config.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (/public_html/wp-content/plugins/tickera-wallet-passes/pass-converter/config.js:17:27) {
  code: 'ERR_REQUIRE_ESM'
}

Node.js v20.14.0

When I run node app.js demo locally it comes back with Listening on http://127.0.0.1:3000 — which is the intended response I’m looking for.

My config.js file is

const stripJsonComments = require('strip-json-comments');
const stripJsonTrailingCommas = require('strip-json-trailing-commas').default;
const fs = require('fs');
const path = require('path');

// The Proxy wrapper ensures config is lazily loaded, so we can redefine
// PASS_CONVERTER_CONFIG_PATH at runtime, which we do in the tests.
module.exports = new Proxy(
  {},
  {
    get(target, prop, receiver) {
      if (this._config === undefined) {
        const configPath = process.env.PASS_CONVERTER_CONFIG_PATH || path.resolve(__dirname, 'config.json');
        this._config = JSON.parse(stripJsonTrailingCommas(stripJsonComments(fs.readFileSync(configPath, 'utf8'))));
        // Most of the entries default to empty strings, but code may expect them to be
        // undefined since they were originally env vars, so filter these out to retain the behavior.
        this._config = Object.fromEntries(Object.entries(this._config).filter(([key, value]) => value !== ''));
      }
      return this._config[prop];
    },
  },
);

I am aware this is related to the way node.js handles module imports (‘require’ instead of ‘import’), but I’m not comfortable rewriting everything. I have tried creating a loader script to dynamically import app.js (Node JS (cpanel) Error: I’m getting an error [ERR_REQUIRE_ESM]: Must use import to load ES Module), I have tried using “jsonc-parser” instead of “strip-json-comments” since it is a CommonJS compatible library but that didn’t work (my JS programming skills are lacking, I probably did it wrong), and I have tried a bunch of different versions of node.js.

I am baffled because I had this error come up 6 months ago when I first tried to implement this on my website, yet somehow I was able to fix it (and of course didn’t write down what I did). I only recently noticed that it stopped working again and can’t figure it out anymore. My web host is running npm 10.7.0, PHP 8.0 (could this be the problem?), and I have it configured to be node.js 20.14.0 (and tried it with 18.20.3 and 16.20.2).

Any advice anyone has is appreciated. The fact that it works locally and not on my web host is the most frustrating!

Try to get value from URL in NextJS

I trying to put value in url and trying to extract value in search.js with router, but I’m getting this error:

TypeError: Cannot read properties of undefined (reading ‘q’)

  <form onSubmit={handleSubmit}>
    <input
      type="text"
      placeholder="Search..."
      value={searchValue}
      onChange={(e) => setSearchValue(e.target.value)}
      class="w-full px-4 py-2 rounded-md text-gray-900"
    />
    <button type="submit">Submit</button>
  </form>
</div>
const handleSubmit = (event) => {
  event.preventDefault(); // Prevent the default form submission
  router.push(`../search?q=${encodeURIComponent(searchValue)}`);
};

Search.js:

const Search = () => {
  const router = useRouter();
  const [searchQuery, setSearchQuery] = useState('');

  useEffect(() => {
    if (router.isReady) {
      setSearchQuery(router.query.q || '');
    }
  }, [router.isReady, router.query.q]);

  if (!router.isReady) {
    return <div>Loading...</div>; // Or some loading indicator
  }

  return (
    <div>
      <p>Search Query: {searchQuery}</p>
    </div>
  );
};

export default Search;