How to hook several state fields in React Component [closed]

useAppStore is a Zustand Store.

I made 3 assumptions based on my understand of React hooks (Please correct me if any of them is wrong)

const MessageList: React.FC<MessageListProps> = ({ popupId }) => {
 const {
    popups,
    isLoading,
    liveResponse: response,
    liveAttachments,
    updateVisibleMessages,
  } = useAppStore();
  1. popups is a list of PopupState. whenever I change a popup by id, for example at PopupState.position.x, I create a new instance of the array popups and change the popup state (new instance too) of that id. (immutability). Since I changed the array of popups, all popups on screen will re-render, which is extremely wasteful because I only want to update position x of one popup by id. Is this correct?

  2. If change the code like this, it will render only when those fields changes, which is the most efficient approach to avoid unnecessary re-render. Is my understanding correct?

    const MessageList: React.FC<MessageListProps> = ({ popupId }) => {
      const themeStyle = useAppStore((state) => state.popups.find((p) => p.id === popupId)?.themeStyle);
      const currentNodeId = useAppStore((state) => state.popups.find((p) => p.id === popupId)?.currentNodeId);
      const messagesMap = useAppStore((state) => state.popups.find((p) => p.id === popupId)?.messagesMap);
      const lastUserMessage = useAppStore((state) => state.popups.find((p) => p.id === popupId)?.lastUserMessage);
      const cachedVisibleMessages = useAppStore((state) => state.popups.find((p) => p.id === popupId)?.cachedVisibleMessages);
    
  3. I hate repeating the state.popups.find((p) => p.id === popupId) so many times, but if I change the code like below, I lose all optimization again. In fact it will be worse because I create a new object instance to wrap the value and when React compares the previous and current value of the hook, it will always think that the state changed even though the fields values itself didn’t change. Is that correct? React does not do deep comparison?

    const { position, title } = useAppStore((state) => ({
      position: state.popups[popupId]?.position,
      title: state.popups[popupId]?.title,
    }));
    

If all my assumptions are correct, how to make the code in 2. look more compact and non-repetitive (DRY)? Is caching it in the store the only solution?

How to hook several state fields in React Component

useAppStore is a Zustand Store.

I made 3 assumptions based on my understand of React hooks (Please correct me if any of them is wrong)

const MessageList: React.FC<MessageListProps> = ({ popupId }) => {
 const {
    popups,
    isLoading,
    liveResponse: response,
    liveAttachments,
    updateVisibleMessages,
  } = useAppStore();
  1. popups is a list of PopupState. whenever I change a popup by id, for example at PopupState.position.x, I create a new instance of the array popups and change the popup state (new instance too) of that id. (immutability). Since I changed the array of popups, all popups on screen will re-render, which is extremely wasteful because I only want to update position x of one popup by id. Is this correct?

  2. If change the code like this, it will render only when those fields changes, which is the most efficient approach to avoid unnecessary re-render. Is my understanding correct?

    const MessageList: React.FC<MessageListProps> = ({ popupId }) => {
      const themeStyle = useAppStore((state) => state.popups.find((p) => p.id === popupId)?.themeStyle);
      const currentNodeId = useAppStore((state) => state.popups.find((p) => p.id === popupId)?.currentNodeId);
      const messagesMap = useAppStore((state) => state.popups.find((p) => p.id === popupId)?.messagesMap);
      const lastUserMessage = useAppStore((state) => state.popups.find((p) => p.id === popupId)?.lastUserMessage);
      const cachedVisibleMessages = useAppStore((state) => state.popups.find((p) => p.id === popupId)?.cachedVisibleMessages);
    
  3. I hate repeating the state.popups.find((p) => p.id === popupId) so many times, but if I change the code like below, I lose all optimization again. In fact it will be worse because I create a new object instance to wrap the value and when React compares the previous and current value of the hook, it will always think that the state changed even though the fields values itself didn’t change. Is that correct? React does not do deep comparison?

    const { position, title } = useAppStore((state) => ({
      position: state.popups[popupId]?.position,
      title: state.popups[popupId]?.title,
    }));
    

Question: If all my assumptions are correct, how to make the code in 2. look more compact and non-repetitive (DRY). Is caching it in the store the only solution?

please help me, beginner

enter image description hereI want to apply width: 100% and height: 100% styles to the element highlighted in blue in the screenshot.

There is a parent element with the ID viewer, and I’d like to use that ID to access the element via the DOM and apply the styles (width: 100%, height: 100%) to it.

However, the is inside an element within that #viewer div. How can I correctly access and style the element in this case?

The exact code please

Why is cubic bezier animation different in CSS vs JavaScript?

I discovered a curious issue when moving an animation with a cubic bezier from CSS into JavaScript: the timing was different. See example below:
(tested in both Chrome and Safari)

document.querySelector('.js-animation').animate([
    { offset: 0.00, transform: 'translateX(0px)', },
    { offset: 0.25, transform: 'translateX(-20px)', },
    { offset: 0.50, transform: 'translateX(40px)', },
    { offset: 0.75, transform: 'translateX(-20px)', },
    { offset: 1.00, transform: 'translateX(0px)', },
],{ 
    duration: 1000, easing: 'cubic-bezier(.36,.07,.19,.97)', iterations: Infinity, 
});
/* just for style */
body { display: flex; flex-direction: column; gap: 20px; padding: 0 40px; }
.box { display: grid; place-items: center; width: 100px; height: 40px; background-color: black; color: white; font: bold 1.5rem sans-serif; }

.css-animation {
    animation: shake 1000ms cubic-bezier(.36,.07,.19,.97) infinite;
}
@keyframes shake { 
    0%   { transform: translateX(0px); }
    25%  { transform: translateX(-20px); }
    50%  { transform: translateX(40px); }
    75%  { transform: translateX(-20px); }
    100% { transform: translateX(0px); }
}
<div class="box css-animation">CSS</div>

<div class="box js-animation">JS</div>

The animation should be the same, so what explains this difference?

Keep at least on tick on the middle of one of the X-axis

I have a chart with two X-Axis . The first is showing the time of the day and the second is showing the date. (https://jsfiddle.net/17puvxd5/26/)
I want to be able to zoom and always keep a value on the second X-axis that is showing the date.

I found a that has a similar behaviour but it’s using only one X-axis (https://jsfiddle.net/23dpb89r/).

events: {
  setExtremes: function(e) {
    if (typeof e.min !== 'undefined' && typeof e.max !== 'undefined') {
      const chart = this.chart;
        points = chart.series[0].points,
        minPoint = points.find(point => point.x >= e.min),
        reversedPoints = points.reverse()
      maxPoint = reversedPoints.find(point => point.x <= e.max);

      if (points.length > 1 && (e.min !== minPoint.x || e.max !== maxPoint.x)) {
        setTimeout(() => chart.xAxis[0].setExtremes(minPoint.x, maxPoint.x), 0)
      }

    }
  }
}

I wasn’t able to replicate it on the X-axis for the date.

Is it possible to achieve this?
Thanks

Focusing input box on keydown causes key to be typed into input box

I was writing code for a MediaWiki .js customization file to focus the search box (an input with id searchInput on most skins) when the / (slash) key is pressed.

I noticed that when I typed the slash, the input box focuses, but the slash is also typed into the input box, which I don’t want.

Here’s a minimal example which seems to have the issue as well:

document.addEventListener("keydown", function (event) {
    if (event.key === '/') {
        const searchInput = document.getElementById("searchInput");
        if (searchInput) {
            searchInput.focus();
        }
    }
});
<input id="searchInput" />

jQuery can be used if needed since it is included with MediaWiki.

How to Center Align Horizontal Bars with Multiple Datasets

I’ve created a bar chart with a couple different datasets, and it works well. However, one dataset is bottom aligned, and the other is top aligned, allowing some minor overlap that would be prettier without. I’d like to just have the bars be centered, so it aligns with the text.

I’ve tried changing bar percentage, category percentage, and playing around with scales (stacked, align, etc).

my horizontal bar chart

const chartLoc = document.getElementById('chart').getContext('2d');
chart = new Chart(chartLoc, {
    type:'bar',
    data: jsonvar,
    options: {
        indexAxis: 'y',  
        layout: {
            padding: {
                right: 100
            }
        },
        plugins: {
            datalabels: {
                labels: {
                    label: {
                        anchor: "end",
                        align: "end",
                        clip: false,
                    }
                }
            }
        }
    },
    plugins: [ChartDataLabels],
});

Get file length for rss.xml enclosure tag in Eleventy

I have the following RSS feed in Eleventy v3.1.1. I wish to add the tag so I can include the featured image in the feed. The tag requires the length of the file in bytes. There are numerous ways to parse a file’s length, but how can I include it in the XML? I assume I’ll have to create some sort of filter in eleventy.js. but I have no idea where to start.

--json
{
  "permalink": "rss.xml",
  "eleventyExcludeFromCollections": true,
  "metadata": {
    "title": "My Website",
    "description": "A neato description",
    "language": "en-US",
    "base": "https://my.site/",
    "author": {
      "name": "John Q. Smith"
    }
  }
}
---
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="{{ metadata.base | addPathPrefixToFullUrl }}" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title><![CDATA[{{ metadata.title }}]]></title>
    <link>{{ metadata.base | addPathPrefixToFullUrl }}</link>
    <atom:link href="{{ permalink | htmlBaseUrl(metadata.base) }}" rel="self" type="application/rss+xml" />
    <description><![CDATA[{{ metadata.description }}]]></description>
    <language>{{ metadata.language or page.lang }}</language>
    <category>Blog</category>
    <copyright>Copyright © 2012{{ helpers.currentYearRSS() | safe }} John Q. Smith. All rights reserved.</copyright>
    <image>
      <url>https://my.site/assets/images/site/logo.png</url>
      <title><![CDATA[{{ metadata.title }}]]></title>
      <link>{{ metadata.base | addPathPrefixToFullUrl }}</link>
      <description><![CDATA[{{ metadata.description }}]]></description>
      <width>144</width>
      <height>144</height>
    </image>
    {%- for post in collections.blog | sortByPubDate | reverse %}
    {%- set absolutePostUrl = post.url | htmlBaseUrl(metadata.base) %}
    <item>
      <title><![CDATA[{{ post.data.title }}]]></title>
      <link>{{ absolutePostUrl }}</link>
      <description><![CDATA[{{ post.data.excerpt }}]]></description>
      <pubDate>{{ post.data.pubdate | dateToRfc822 }}</pubDate>
      <lastBuildDate>{{ post.date | dateToRfc822 }}</lastBuildDate>
      <dc:creator>{{ metadata.author.name }}</dc:creator>
      <guid>{{ absolutePostUrl }}</guid>
      <enclosure url="https://my.site/{{ post.data.image }}"
    length="" type="image/jpeg" />
    </item>
    {%- endfor %}
  </channel>
</rss>

Storing a variable without changing its value and storing a variable that changes its value

I have two codes. The first uses the variable b, and the second uses the variable a. The variable b does not change its value, while the variable a changes its value multiple times in the for loop. I get the same performance result for both codes. Why ???

Code 1 :

    var A = performance.now();
    var b = 5;
    let a = 0;
    const demo = document.getElementsByClassName("demo");
    for (let i = 0; i < demo.length; i++) {
        demo[i].addEventListener("click", function() {
            a += i;
            this.style.color = "red";
        });
    }
    demo[0].click();
    document.getElementById("femo").addEventListener("click", function() {
        for (let i = 0; i < demo.length; i++) {
            demo[i].innerHTML = b;
        }
    });
    var B = performance.now();
    alert(B-A);

code 2 :

    var A = performance.now();
    var b = 5;
    let a = 0;
    const demo = document.getElementsByClassName("demo");
    for (let i = 0; i < demo.length; i++) {
        demo[i].addEventListener("click", function() {
            a += i;
            this.style.color = "red";
        });
    }
    demo[0].click();
    document.getElementById("femo").addEventListener("click", function() {
        for (let i = 0; i < demo.length; i++) {
            demo[i].innerHTML = a;
        }
    });
    var B = performance.now();
    alert(B-A);

How to set seprate IFRAME body to each TextArea in view page using TextArea(Kendo) [Seting up Max Limit to text area]

I am working on a project which contain multiple textarea (Kendo editor). I want to set character limit to each textArea. I have tried achieve that using max length , setting keyDown and focus event but nothing works. I am not sure if this because of the Kendo editor or not. I got below link (Kendo UI Editor max and minimum characters) from that I come to below solution, but this solution adds a single iframe element for all textarea elements. The keydown event of any textarea affects the character limit message of all the textArea elements. I am looking for help achieve working with independent textarea elements.

HTML code:

<form class="LandindPage">
  <div class="form-group">
    <label>
      Heading 1 (0-100 character) <span class="mandatory">*</span>
    </label>
     
    <textarea
      class="kendo-input-editor"
      id="HeadingMessage1"
      onkeydown="HeadingMessage1Validation()"
      aria-label="editor"
      disabled
    >
      @Html.Raw(Model.HeadingMessage1)
    </textarea>
    <p class="text-warning">
      Heading 1 Character Count: <span class="text-warning" id="Head1textCount"></span>
    </p>
  </div>
  <div class="form-group">
    <label>
      Heading 2 (0-100 character) <span class="mandatory">*</span>
    </label>
    <textarea
      class="kendo-input-editor"
      id="HeadingMessage2"
      onkeydown="Heading2Validation()"
      aria-label="editor"
      disabled
    >
      @Html.Raw(Model.HeadingMessage2)
    </textarea>
    @* <p class="text-warning">Heading 2 Character Count: <span class="text-warning" id="Head2textCount"></span></p> *@
  </div>
</form>
$(document).ready(function () {
    $(function HeadingMessage1Validation() {       
        var minChar = 1;
        var maxChar = 100;
        var iframe1 = $("iframe");
        var HeadMsg1 = $("#HeadingMessage1").val();
        var kendoDecode=htmlDecode(HeadMsg1);
        var HtmltagReplace = removeTags(kendoDecode);
        var CharCount = HtmltagReplace.length;

        // Change event for iframe body content
        iframe1.contents().find("body").on('keydown', function (e) {
            // Clean up
            textarea.disabled = true;

            // Get Body (.text() strips out HTML tags)
            var data = $(this).text();
            if (this.which < 32) {
                return; // Do nothing
            }

            var isEditKey = (e.keyCode == 8 || e.keyCode == 46);

            if (data.length == maxChar && !isEditKey) {
                $("#Head1textCount").text(data.length + " of Maximum Limit (100 Character) Warning : Maximum Limit Reached");
                e.preventDefault();
            } else if (data.length > maxChar) {
                // Maximum exceeded
                $(this).text(data.substring(0, maxChar));
            } else if (data.length < minChar) {
                $("#Head1textCount").text(data.length + " of Maximum Limit (100 Character)");
            } else {
                $("#Head1textCount").text(data.length + " of Maximum Limit (100 Character)");
            }
        });

        // OnLoad call to get starting count
        $("#Head1textCount").text(CharCount + " of Maximum Limit (100 Character)");
    });
});

Booking data filter by today’s date and later [closed]

i have made a website where you can make bookings and on your profile you will be able to see your bookings, but i want to filter it so you can only see the bookings from today and later, but idk how to do it

i have done this for now but now it says on my profile that there are no bookings even though there should be some shown

export async function loader({ request }: Route.LoaderArgs) {
  const session = await getSession(request.headers.get("cookie"));
  const authUserId = session.get("authUserId");

  if (!authUserId) {
    throw redirect("/signin");
  }

  const user = await User.findById(authUserId).lean();

  // Get today's date at 00:00:00 UTC
  const now = new Date();
  const todayUTC = new Date(
    Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())
  );

  // Only show bookings that end today or in the future
  const bookings = await Booking.find({
    user: authUserId,
    startDate: { $gte: todayUTC },
  })
    .sort({ startDate: 1 })
    .lean();

  return { bookings: JSON.parse(JSON.stringify(bookings)), user };
}

How would you use JSDoc for VSCode intellisense on an extended class method

I’m working on a library, and would like some functionality that requires users (meaning the user of the library) to extend a class. On that class will be a method that the user should override, and which takes in a specific parameter. It might look something like this:

class BaseClass {
    /**
     * @param {context} context
     */
    myMethod(context) {
        console.warn('myMethod should be overwritten')
    }
}

class UsersClass extends BaseClass {
    myMethod(context) {
        /*...*/
    }
}

/**
 * @typedef {Object} context
 * 
 * @prop {String} contextString
 * @prop {Number} someNumber
 * etc.
 */

The problem is, when the user goes to write myMethod, there won’t be any intellisense for the context parameter (ie. context.contextString, etc. won’t show up).

Is there any way to add this without requiring users to get an extension, etc?

extra message shows

Problem Description

I have integrated webchat.js with Microsoft Copilot Studio using the Direct Line API. When programmatically sending messages back to the bot using the Web Chat dispatch action,
Copilot Studio is displaying the intended message but is also generating an additional unwanted message immediately after. (Please see screenshot)

Technical Details

Integration Setup:

  • Web Chat JS integrated with Copilot Studio
  • Using Direct Line API for communication
  • Dispatching messages programmatically via Web Chat store

Code Implementation:

if (userresponse === "disLiked") {
  // Send a message back to the bot
  store.dispatch({
    type: 'WEB_CHAT/SEND_MESSAGE',
    // type: 'DIRECT_LINE/POST_ACTIVITY',
    payload: {
      text: apologyMessage,
    }
  });
  return; // tried this as well
}

Expected Behavior:

  • Bot should display only the apologyMessage when user response is “disLiked”
  • No additional messages should appear

Actual Behavior:

  • Bot displays the intended apologyMessage correctly
  • An extra, unwanted message appears immediately after
  • This extra message disrupts the user experience