Javascript regex ignore characters between capture groups

In javascript, I’m trying to capture some optional groups but I always struggle with regular expressions!
I don’t know how to allow for any characters to appear between capture groups

This is what I have so far:

/(((.*?)))+([(.*?)])?(<<(.*?)>>)?(|(.*?)|)?/g

It’s supposed to capture anything between (), then optionally anything between [], then optionally anything between <<>> and finally, optionally anything between ||

Running that expression over this string….

Presentation on <strong>(date)[presentation-date]<<&today>></strong>|{"placeholder":"Type summary"}|

…captures (date), [presentation-date] and <<&today>> but it doesn’t capture |{"placeholder":"Type summary"}|

I’ve worked out that it’s because of the </strong> between <<&today>> and |{"placeholder":"Type summary"}| but I don’t know how to allow for any characters to be between the optional capture groups (<<(.*?)>>) and (|(.*?)|)

I’ve tried different placings of (?:.*) in the hope that would ignore anything between capture groups but I still can’t get it to work.

Can anyone please show me what I’m missing?

Nextjs application not running

I need help with figuring out an error.

I’m running an os of windows 10pro.

whenever I try loading the page of the app from the code-refactor-branch,

the page loads up for a second, then displays an error Application error: a client-side exception has occurred (see the browser console for more information)..

but then when I check the console I see this:

use-reducer-with-devtools.js?12360:95 Uncaught Error: Invariant: Missing ActionQueueContext
    at useReducerWithReduxDevtoolsImpl (use-reducer-with-devtools.js?12360:95:15)
    at Router (app-router.js?bdea0:225:100)
    at renderWithHooks (react-dom.development.js:11121:18)
    at mountIndeterminateComponent (react-dom.development.js:16869:13)
    at beginWork$1 (react-dom.development.js:18458:16)
    at HTMLUnknownElement.callCallback (react-dom.development.js:20565:14)
    at Object.invokeGuardedCallbackImpl (react-dom.development.js:20614:16)
    at invokeGuardedCallback (react-dom.development.js:20689:29)
    at beginWork (react-dom.development.js:26949:7)
    at performUnitOfWork (react-dom.development.js:25748:12)
useReducerWithReduxDevtoolsImpl @ use-reducer-with-devtools.js?12360:95
Router @ app-router.js?bdea0:225
renderWithHooks @ react-dom.development.js:11121
mountIndeterminateComponent @ react-dom.development.js:16869
beginWork$1 @ react-dom.development.js:18458
callCallback @ react-dom.development.js:20565
invokeGuardedCallbackImpl @ react-dom.development.js:20614
invokeGuardedCallback @ react-dom.development.js:20689
beginWork @ react-dom.development.js:26949
performUnitOfWork @ react-dom.development.js:25748
workLoopConcurrent @ react-dom.development.js:25734
renderRootConcurrent @ react-dom.development.js:25690
performConcurrentWorkOnRoot @ react-dom.development.js:24504
workLoop @ scheduler.development.js:256
flushWork @ scheduler.development.js:225
performWorkUntilDeadline @ scheduler.development.js:534Understand this errorAI
hook.js:608 Warning: An error occurred during hydration. The server HTML was replaced with client content in <#document>.
overrideMethod @ hook.js:608
window.console.error @ app-index.js:33
console.error @ hydration-error-info.js?f2611:63
printWarning @ react-dom.development.js:94
error @ react-dom.development.js:68
errorHydratingContainer @ react-dom.development.js:36301
recoverFromConcurrentError @ react-dom.development.js:24593
performConcurrentWorkOnRoot @ react-dom.development.js:24542
workLoop @ scheduler.development.js:256
flushWork @ scheduler.development.js:225
performWorkUntilDeadline @ scheduler.development.js:534Understand this errorAI
use-reducer-with-devtools.js?12360:95 Uncaught Error: Invariant: Missing ActionQueueContext
    at useReducerWithReduxDevtoolsImpl (use-reducer-with-devtools.js?12360:95:15)
    at Router (app-router.js?bdea0:225:100)
    at renderWithHooks (react-dom.development.js:11121:18)
    at mountIndeterminateComponent (react-dom.development.js:16869:13)
    at beginWork$1 (react-dom.development.js:18458:16)
    at HTMLUnknownElement.callCallback (react-dom.development.js:20565:14)
    at Object.invokeGuardedCallbackImpl (react-dom.development.js:20614:16)
    at invokeGuardedCallback (react-dom.development.js:20689:29)
    at beginWork (react-dom.development.js:26949:7)
    at performUnitOfWork (react-dom.development.js:25748:12)
useReducerWithReduxDevtoolsImpl @ use-reducer-with-devtools.js?12360:95
Router @ app-router.js?bdea0:225
renderWithHooks @ react-dom.development.js:11121
mountIndeterminateComponent @ react-dom.development.js:16869
beginWork$1 @ react-dom.development.js:18458
callCallback @ react-dom.development.js:20565
invokeGuardedCallbackImpl @ react-dom.development.js:20614
invokeGuardedCallback @ react-dom.development.js:20689
beginWork @ react-dom.development.js:26949
performUnitOfWork @ react-dom.development.js:25748
workLoopSync @ react-dom.development.js:25464
renderRootSync @ react-dom.development.js:25419
recoverFromConcurrentError @ react-dom.development.js:24597
performConcurrentWorkOnRoot @ react-dom.development.js:24542
workLoop @ scheduler.development.js:256
flushWork @ scheduler.development.js:225
performWorkUntilDeadline @ scheduler.development.js:534Understand this errorAI
hook.js:608 The above error occurred in the <Router> component:

    at Router (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js?bdea0:207:11)
    at ErrorBoundaryHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js?28e40:113:9)
    at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js?28e40:160:11)
    at AppRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js?bdea0:585:13)
    at ServerRoot (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:112:27)
    at Root (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:117:11)

React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundaryHandler.
overrideMethod @ hook.js:608
window.console.error @ app-index.js:33
console.error @ hydration-error-info.js?f2611:63
logCapturedError @ react-dom.development.js:15295
update.callback @ react-dom.development.js:15344
callCallback @ react-dom.development.js:8696
commitCallbacks @ react-dom.development.js:8743
commitClassCallbacks @ react-dom.development.js:21323
commitLayoutEffectOnFiber @ react-dom.development.js:21425
recursivelyTraverseLayoutEffects @ react-dom.development.js:22926
commitLayoutEffectOnFiber @ react-dom.development.js:21407
recursivelyTraverseLayoutEffects @ react-dom.development.js:22926
commitLayoutEffectOnFiber @ react-dom.development.js:21407
recursivelyTraverseLayoutEffects @ react-dom.development.js:22926
commitLayoutEffectOnFiber @ react-dom.development.js:21407
recursivelyTraverseLayoutEffects @ react-dom.development.js:22926
commitLayoutEffectOnFiber @ react-dom.development.js:21407
recursivelyTraverseLayoutEffects @ react-dom.development.js:22926
commitLayoutEffectOnFiber @ react-dom.development.js:21577
recursivelyTraverseLayoutEffects @ react-dom.development.js:22926
commitLayoutEffectOnFiber @ react-dom.development.js:21577
recursivelyTraverseLayoutEffects @ react-dom.development.js:22926
commitLayoutEffectOnFiber @ react-dom.development.js:21577
recursivelyTraverseLayoutEffects @ react-dom.development.js:22926
commitLayoutEffectOnFiber @ react-dom.development.js:21437
commitLayoutEffects @ react-dom.development.js:22912
commitRootImpl @ react-dom.development.js:26226
commitRoot @ react-dom.development.js:26077
commitRootWhenReady @ react-dom.development.js:24749
finishConcurrentRender @ react-dom.development.js:24714
performConcurrentWorkOnRoot @ react-dom.development.js:24559
workLoop @ scheduler.development.js:256
flushWork @ scheduler.development.js:225
performWorkUntilDeadline @ scheduler.development.js:534Understand this errorAI
react-dom.development.js:16571 Uncaught Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
    at updateHostRoot (react-dom.development.js:16571:57)
    at beginWork$1 (react-dom.development.js:18486:14)
    at beginWork (react-dom.development.js:26927:14)
    at performUnitOfWork (react-dom.development.js:25748:12)
    at workLoopSync (react-dom.development.js:25464:5)
    at renderRootSync (react-dom.development.js:25419:7)
    at recoverFromConcurrentError (react-dom.development.js:24597:20)
    at performConcurrentWorkOnRoot (react-dom.development.js:24542:26)
    at workLoop (scheduler.development.js:256:34)
    at flushWork (scheduler.development.js:225:14)

I have tried deleting both node_modules and .next files and tried reinstalling them, still the same issue.

kindly note: as at saturday everything was working fine, until, I upgraded my system later on that same saturday, thereby having to reinstall windows 10pro.

I’d like to know if anyone have had similar issue

MUI X-data-grid how to update selected rows

I have an mui-x-data grid that I attemp to update one of the columns on for selected rows.
I run code below when I trigger the update on selection but status columns(which is a string) doe not get set and redrawn to new state of ‘active’.
Is this the correct way to trigger the row update and redraw?

  const updateSelectedtoActive = () => {
    const selectedRows=apiref.current.getSelectedRows();
    for( let i=0; i< selectedRows.keys.length; i++){
      const id =selectedRows.keys[i];
      apiref.current.updateRows([{ id: id, status: 'active' }]);      
    }
  }

JS animation with Element.animate method throws error about offset range

I’m trying to create an animation without using any CSS file. To do so, I’m using a React app and the .animate method to manage keyframes. The animation is a wiggle.

When trying the following code, React throws this error:

Failed to execute 'animate' on 'Element': timeline offset must be a range offset pair. Missing the offset. TypeError: timeline offset must be a range offset pair. Missing the offset.

const animateWiggle = () => {
  let top = document.getElementById("top")

  top.animate([
      {
        offset: [0.1, 0.9],
        transform: "translate(-50%) translate3d(-1px, 0, 0)",
      },
      {
        transform: "translate(-50%) translate3d(2px, 0, 0)",
        offset: [0.2, 0.8]
      },
      {
        transform: "translate(-50%) translate3d(-4px, 0, 0)",
        offset: [0.3, 0.5, 0.7]
      },
      {
        transform: "translate(-50%) translate3d(4px, 0, 0)",
        offset: [0.4, 0.6]
      }
   ], {
     duration: 1000,
     iterations: Infinity,
     }
    )
   }

useEffect(() => {
 animateWiggle()
}, [])

// ...

return (
   <img
     src={topImage}
     id={"top"}
   />
)

Note that this works with pure CSS, but my whole intention here is to convert CSS animations into pure javascript in order to modify its properties within the app.

The original CSS animation:

@keyframes wiggle {
    10%,
    90% {
        transform: translate(-50%) translate3d(-1px, 0, 0);
    }

    20%,
    80% {
        transform: translate(-50%) translate3d(2px, 0, 0);
    }

    30%,
    50%,
    70% {
        transform: translate(-50%) translate3d(-4px, 0, 0);
    }

    40%,
    60% {
        transform: translate(-50%) translate3d(4px, 0, 0);
    }
}

How can i use TS in this situation

I have in my app on React component named Jornal. It is a list of documents. And I have about 30 types of jornals.
On nodejs i make interface description of each jornal. So jornals are typed by TS.

But how I can use type info to work with data from backend on front?

On frontend in Jornal component i use custom hook to get data from backend. After data received it saved to react state of jornal component.
And ones data received jornal component render list. Each row of the list is separate component depended on type of jornal.

So how I can use TS interface in custom hook which receive data from backend? how I can make jornal react state typed?

Thanks

File pathing & access across app, design system, and 3rd party lib

Running into an issue where a 3rd party library (intl-tel-input) that’s used in a design system library (my-design-system) as part of a “UserProfile” component has some broken visual styles when the design system is used in an app (my-app) due to incorrect file pathing and resolution. Its not clear to me where in the chain the issue lies.

How it looks in my-design-system

enter image description here

How it looks in my-app

enter image description here

When looking in the networking dev tools for my-app you can see the 404s where the images are failing to load, and its clear the path isn’t correct, however if I look for those same file names I can see them in my-design-system/dist but obviously the issue has to do with the resolution of those files, especially considering I don’t know what the names of those files will be at build.

enter image description here

How can I best solve this issue?

DOM element not updated in select2 event handlers (select/unselect) function

Struggling long time on styling select2 tags (valid/invalid) as after unselecting a tag (select2:unselect event) DOM element’s state (selected by jQuery) not reflected in handler function.

Context:
I have a select2 field in my form which has not options available in dropdown as input serves for creation of new objects with select2 tags: true parameter.

On tag selected ajax GET request performed to check if such an object exists. If it is then the tag styled to indicate it invalid state. It runs well on adding new tags. However if I unselect even single tag the rest “invalid” tags restores to default and all styles resets.
During debugging I found that when select2:unselect handler triggers (tag already unselected and removed from DOM inspector in browser) parent’s container references to children which parameters not actual as per DOM (console.log() printing children having class which not actually assigned at that moment but was assigned before select2: unselect event triggered).

let invalidTags = new Set();

function validateCustomTag() {
    var tags = $("#serials-form").find("li.select2-selection__choice");

    tags.each(function () {
        const tag = $(this); // Get the current tag element
        const serialNumber = tag.attr("title");

        // Proceed with AJAX validation
        $.ajax({
            type: "GET",
            url: SERIAL_NUMBER_VALIDATION_URL,
            data: { serial_number: serialNumber },
            dataType: "json",
            success: function (data) {
                const response = data.response;

                if (!response.valid) {
                    // Add the invalid serial number to the Set
                    invalidTags.add(serialNumber);

                    // Append error message
                    const errorElement = `<li>${response.error}</li>`;
                    $("#snAjaxErrors").removeClass("d-none");
                    $("#snAjaxErrors").append(errorElement);

                }
            },
        });
    });
} 

function applyInvalidStyles() {
    invalidTags.forEach((sn) => {
        const select2FieldContainer = $("#serials-form")
        let tag = select2FieldContainer.find(`li[title=${sn}]`)
        tag.addClass("bg-danger bg-opacity-50 text-light");
    });       
}

$(document).ready(function () {
    $("#id_serial_numbers").on("select2:select", function () {
        validateCustomTag();
        applyInvalidStyles();  
    });

    $("#id_serial_numbers").on("select2:unselect", function () {  
        // Reapply invalid styles after any redraw
        applyInvalidStyles();
    });
)};

Mikro-Orm Error: No driver specified when Run Mikro Orm Migration Commands against Compiled Js Files

I know there is a similar issue here but it seems not solving my issue. I also opened a github discussion here

Summary

When using MikroORM with a configuration file bundled by Webpack, the migration commands MIKRO_ORM_CLI_USE_TS_NODE=false npx mikro-orm debug/migration-check against compiled js files fail with the following error:

Error: No driver specified, please fill in the `driver` option or use `defineConfig` helper (to define your ORM config) or `MikroORM` class (to call the `init` method) exported from the driver package (e.g. `import { defineConfig } from '@mikro-orm/mysql'; export defineConfig({ ... })`).
    at Configuration.validateOptions (tryAndError/node_modules/@mikro-orm/core/utils/Configuration.js:374:19)
    at new Configuration (node_modules/@mikro-orm/core/utils/Configuration.js:152:18)
    at ConfigurationLoader.getConfiguration (tryAndError/node_modules/@mikro-orm/core/utils/ConfigurationLoader.js:103:16)
    at async CLIHelper.getORM (tryAndError/node_modules/@mikro-orm/cli/CLIHelper.js:26:25)
    at async MigrationCommandFactory.handleMigrationCommand (tryAndError/node_modules/@mikro-orm/cli/commands/MigrationCommandFactory.js:85:21)

The issue does not occur in development mode (run mikro-orm commands against ts files), where the configuration resolves correctly. Upon inspecting the configuration options by modifying the files inside node_modules/@mikro-orm/core/utils/Configuration.js using console.log(options), the options differ between development and production:

Development: Options resolve as expected.

Production: Options appear to default to the raw constructor without the expected configuration values.

Minimum Reproducible Example

# mikro-orm.config.ts

import type { AbstractSqlDriver } from '@mikro-orm/mysql';
import { MySqlDriver } from '@mikro-orm/mysql';
import type { MikroOrmModuleOptions } from '@mikro-orm/nestjs';
import { User } from './src/app/entity';
import { CLIHelper } from '@mikro-orm/cli';
import { Migrator } from '@mikro-orm/migrations';

console.log('To avoid tree shaking...', CLIHelper.getNodeVersion());
const MIKRO_ORM_CONFIG: MikroOrmModuleOptions<AbstractSqlDriver> = {
  entities: [User],
  name: 'test',
  driver: MySqlDriver,
  port: 3306,
  forceUtcTimezone: true,
  dbName: process.env.name,
  host: process.env.host,
  user: process.env.user,
  password: process.env.password,
  discovery: { disableDynamicFileAccess: true },
  migrations: {
    tableName: 'migrations',
    path: './migrations',
  },
  allowGlobalContext: process.env.MIKRO_ORM_ALLOW_GLOBAL_CONTEXT === 'true',
  extensions: [Migrator]
};

export default MIKRO_ORM_CONFIG;
# entity/user.ts

import { Entity, PrimaryKey } from '@mikro-orm/core';
import { Exclude, Expose } from 'class-transformer';

@Entity({ tableName: 'users' })
@Exclude()
export class User {
  @PrimaryKey()
  @Expose()
  id!: number;
}

Steps to Reproduce

  1. clone this sample repo here
  2. install dependencies npm install
  3. build project nx run tryAndError:build
  4. cd into dist/apps/tryAndError
    Run MIKRO_ORM_CLI_USE_TS_NODE=false npx mikro-orm migration:check
    Then you will see the error.

Run the migration commands agains the ts files in the root level, no error occurs.

Redundant calculations and re-renders in JavaScript. Storing and accessing data in objects and arrays

The question is about the performance and the use of right reference data type.

I wonder how to improve performance and reduce unnecessary re-renders or mapping/filtering.

The app overview:

I have a react native app for managing tasks or more simply todos app.

The user can create multiple lists with many tasks. The tasks have deadline, completion status and other properties.

I store the data in zustand under one property: lists. Lists are an object, and each list contains items which are objects as well.

lists:

{
  "1737818490661": {
    "id": 1737818490661,
    "title": "Title",
    "description": "Description",
    "createdAt": "2025-01-25T15:21:30.661Z",
    "deadline": null,
    "completed": false,
    "progress": 0,
    "showListsDeadline": false,
    "showProgressBar": false,
    "showCompleted": false,
    "showOriginalIndex": false,
    "items": {
      "1737818490662": {
        "id": 1737818490662,
        "title": "Task Title",
        "completed": false,
        "listId": 1737818490661,
        "latinized": "Task Title",
        "itemDeadline": "2025-01-27T15:22:00.000Z"
      },
      "1737905755884": {
        "title": "Task Title 2",
        "latinized": "Task Title 2",
        "completed": false,
        "id": 1737905755884,
        "listId": 1737818490661
      },
    },
    "latinized": "Title",
    "lastActivity": "2025-01-27T09:19:42.674Z",
    "currentItemSort": "index",
    "listLength": 4,
    "closestItemDeadline": "2025-01-27T15:22:00.000Z"
  }
}

In the main component the lists are mapped into an array to be displayed in the FlatList.

A listItem contains items object which is mapped into an array and stripped of most values but title and id. The rest of the values are accessed through lists[listId].items[itemId]

WHY?

  • the FlatList renders items by ID, meaning if an item changes it does not need to re-render the whole list. Within that item the data is get() from the store. // but the data needs to be mapped initially

  • the lists and items are stored as object for easier access. Apparently find() is very performance heavy // but the lists’ data needs to be mapped on every change

LISTS COMPONENT

const List = () => {
  const rawLists = useZustandStore(state => state.lists)
  const currentSort = useZustandStore(state => state.currentSort)
  const showCompleted = useZustandStore(state => state.showCompletedLists)

  const searchQuery = useSelector(selectors.selectSearch)

  const renderList = useCallback(
    ({ item }) => <ListItemWithActions item={item} rowRefs={rowRefs} />,
    [],
  )

  const lists = useMemo(
    () =>
      Object.keys(rawLists)
        .map((key, index) => ({
          id: key,
          ...rawLists[key],
          items: Object.values(rawLists[key].items),
          itemIndex: index + 1,
        }))
        .sort((a, b) => a.id - b.id),
    [rawLists],
  )

  const searchList = (items, query) => {
    if (!query) {
      return null
    }

    const lowerLatinQuery = latinize(query?.toLowerCase())
    return items.filter(item => {
      return (
        item.latinized.toLowerCase().includes(lowerLatinQuery) ||
        item?.description?.toLowerCase().includes(lowerLatinQuery) ||
        item?.items?.some(subItem =>
          subItem?.latinized?.toLowerCase().includes(lowerLatinQuery),
        )
      )
    })
  }

  const sortedLists = useSortedLists({ currentSort, lists })

  const filteredLists = useMemo(() => {
    return sortedLists.filter(item => showCompleted || !item.completed)
  }, [sortedLists, showCompleted])

  const queriedItems = searchList(sortedLists, searchQuery)

  return (
    <Animated.FlatList
      data={queriedItems || filteredLists}
      removeClippedSubviews={false}
      renderItem={renderList}
      keyExtractor={keyExtractor}
    />
  )
}

LISTITEM COMPONENT

const ListItem = ({
  route
}) => {
  const lists = useZustandStore(state => state.lists)

  const itemIdParams = route.params?.item?.id

  const list = lists[itemIdParams]

  const listId = list?.id

  const currentItemSort = list?.currentItemSort

  const showCompleted = list?.showCompleted || false

  const showOriginalIndex = list?.showOriginalIndex || false

  const itemsAsObjects = list?.items

  const {
    arrayOfItemIds,
    arrayOfAllItems,
    nonCompletedItems,
    lastItemExistsAndHasTitle,
  } = useMemo(() => {
    const arrayOfItemIds = []
    const arrayOfAllItems = []
    const nonCompletedItems = []
    let lastItemId = null
    if (itemsAsObjects) {
      Object.keys(itemsAsObjects).forEach((key, index) => {
        const item = itemsAsObjects[key]
        const listId = itemsAsObjects[key]?.listId
        const strippedItem = {
          id: key,
          listId,
          itemIndex: index + 1,
        }

        arrayOfItemIds.push(strippedItem)
        arrayOfAllItems.push({
          ...item,
          listId,
          itemIndex: index + 1,
        })

        if (!item.completed) {
          nonCompletedItems.push(strippedItem)
        }

        if (item.completed) {
          completedCount++
        }

        lastItemId = key
      })

      arrayOfItemIds.sort((a, b) => a.id - b.id)
      nonCompletedItems.sort((a, b) => a.id - b.id)
    }

    return {
      arrayOfItemIds,
      arrayOfAllItems,
      nonCompletedItems,
      lastItemId,
      lastItemExistsAndHasTitle,
    }
  }, [itemsAsObjects])

  const searchItems = (items, query) => {
    if (!query) {
      return null
    }

    const lowerLatinQuery = latinize(query?.toLowerCase())

    return items.filter(item => {
      return item.latinized.toLowerCase().includes(lowerLatinQuery)
    })
  }

  const queriedItems = searchItems(arrayOfAllItems, searchQuery)

  const sortedItems = useSortedItems({
    currentSort: currentItemSort || 'index',
    items: arrayOfAllItems,
    completed: showCompleted,
  })

  const renderItem = useCallback(
    ({
      item,
      index
    }) => {
      return ( <
        ItemWithActions item = {
          item
        }
        index = {
          index
        }
        listId = {
          listId
        }
        showCompleted = {
          showCompleted
        }
        showOriginalIndex = {
          showOriginalIndex
        }
        arrayOfItemIdsLength = {
          arrayOfItemIds.length
        }
        nonCompletedItemsLength = {
          nonCompletedItems.length
        }
        />
      )
    },
    [
      listId,
      showCompleted,
      showOriginalIndex,
      arrayOfItemIds.length,
      nonCompletedItems.length,
    ],
  )

  return ( <
    KeyboardAwareFlatList as = {
      Animated.FlatList
    }
    data = {
      searchQuery ? queriedItems : sortedItems
    }
    renderItem = {
      renderItem
    }
    keyExtractor = {
      keyExtractor
    }
    />
  )
}

If you read the snippets you can see that the data is formatted many times before it is being displayed. Stripping items of values looks like a good idea but I still need the stripped values in case the user uses search bar to look through the titles. Similarly with lists.

Are all those calculations necessary? Should I use arrays or objects?

There is an additional issue with the “special lists”
Those are the lists that gather all the items with today’s tomorrow’s or overdue deadlines and put them in one list (or 3 in this case) If I create those lists by filtering, they will need to be recalculated every time anything changes, as the root object will change. How not to lose performance?

Imagine a 100 lists with 100 items each.

Handling Infinite Spinner on Browser Back After PayPal Redirect in React Checkout

I’m working on a React checkout page where after clicking the PayPal submit button, I get a 3-second loading spinner, and then I am redirected to the PayPal site. However, when I click the browser’s back button to return to the checkout page, I encounter an issue where the page is stuck with an infinite spinning loader and an overlay that prevents interaction.

I’m currently using templateContext?.isLoading boolean to control the loading state, but I want to avoid reloading the page when navigating back. Ideally, I’d like to set isLoading to false if the previous page was the PayPal redirect page, instead of reloading the entire page.

My main goal is to find a solution to track the previous page (for example, check if it was PayPal) and either stop the loading spinner or prevent the overlay from blocking interaction without reloading the page.

Has anyone faced a similar issue or know of a way to handle this in React?

Why Doesn’t the setTimeout Callback Run Immediately After the Call Stack Is Empty in JavaScript?

const example0 = () => {
  setTimeout(() => {
    console.log("example 0");
  }, 0);
};

const example1 = () => {
  setTimeout(() => {
    console.log("example 1");
  }, 0);
  for (let i = 0; i < 10; i++) {
    console.log(i);
  }
  example2();
};

const example2 = () => {
  console.log("example 2");
  example3();
};

const example3 = () => {
  console.log("example 3");
};

example0();
example1();

Shouldn’t this code work like this?: The example1 function is called. The example1 function is in the call stack. When it encounters setTimeout, it is passed to the setTimeout Web API, and the timer starts. Since the timer is set to 0ms, the callback enters the callback queue immediately, waiting for the call stack to be empty. Once the example1 function finishes, the call stack is empty. When the call stack is empty, it should execute the setTimeout callback before running example1’s remaining code. However, the result isn’t like that. After all the nested functions inside example0 and example1 have run, the setTimeout callback runs. Why is that? Actually, isn’t the call stack empty after example0 finishes?

output
0
1
2
3
4
5
6
7
8
9
example 2
example 3
example 0
example 1


Expected Output
example 0
0
1
2
3
4
5
6
7
8
9
example 2
example 3
example 1

OnLoad Event on Picture Element?

In order to lazyload images with a fade effect, I use JavaScript with Intersection Observer. When an image enters the viewport, the following two things happen:

  1. The content of data-srcset and data-src is transferred to srcset and src. The image loads.
  2. Once loaded, the image fades in using the onload event and CSS.

My problem is the following: I’m now using the picture element, with source and img, and I’m trying to adapt this script. It seems that onload is not compatible with source and picture elements. By targeting only the img element, the fade effect starts too early, while source is not yet loaded.

Would it be possible to fade the whole picture element once the source and img inside are loaded? Or to fade the figure element, above it?

RTK Query `isLoading` state gets `false` before data has been fetched

I have this API that handles getting data from Socket connection:

import { api } from "../../api";
import { createSocketFactory } from "@/services/socket";

import type { Coin } from "@/interfaces/global/coin.types";

export const pricesApi = api.injectEndpoints({
  endpoints: (build) => ({
    getCoinPrices: build.query<Coin[], void>({
      queryFn: () => ({ data: [] }),
      onCacheEntryAdded: async (
        arg,
        { updateCachedData, cacheDataLoaded, cacheEntryRemoved }
      ) => {
        // Create the socket IO instance and start the connection when the cache subscription starts
        const socket = await createSocketFactory();

        try {
          // Wait for the initial query to resolve before proceeding
          await cacheDataLoaded;

          // Listen for price updates
          const listener = (data: Coin[]) => {
            updateCachedData(() => data);
          };

          // Start listening for price updates
          socket.on("prices", listener);
        } catch (error) {}

        // `cacheEntryRemoved` will resolve when the cache subscription is no longer active
        await cacheEntryRemoved;

        // Perform cleanup steps once the `cacheEntryRemoved` promise resolves
        socket.off();
        socket.disconnect();
      },
    }),
  }),
});

export const { useGetCoinPricesQuery } = pricesApi;

In a component when I get the data, the isLoading is set to true but immediately it’s set to false before the data has been fetched from the connection. It actually gets false here:

enter image description here

Is this behavior expected? Because I have used the same way of handling Socket connection in another project that used RTK v1.9 and the isLoading would get false after the data was loaded.
How can I track the loading state if this is not an actual issue?

Omnipay: Payment failed: Authentication failed due to invalid authentication credentials or a missing Authorization header

I’m using Omnipay for Paypal payments, I’m getting this error:

Payment failed: Authentication failed due to invalid authentication credentials or a missing Authorization header.  

This is my code for the sale, I have checked with several accounts and both give an error. So, I find it hard to believe that it is a credentials error.

public function generatePaypalPaymentByTransaction(Transaction $transaction) {
    try {
        $gateway = Omnipay::create('PayPal_Rest');
        $gateway->setClientId(config('paypal.client_id'));
        $gateway->setSecret(config('paypal.secret'));
        $gateway->setTestMode(config('paypal.test_mode'));
        
        
        $urlHost = rtrim(config('paypal.url_host'), '/') . '/';

        if($transaction->type != Transaction::DEPOSIT_TYPE) {
            $username = User::find($transaction->recipient_user_id)->username;
            $username = rawurlencode($username); // Codificar el username para la URL
        }
        $returnUrl = $urlHost . 'pay/execute-payment' . '?transaction_id=' . $transaction->id;
        
        if($transaction->type == Transaction::ROULETTE) {
            $cancel_url = $urlHost . 'roulette/' . $username . '/' . $transaction->roulette_id;
        } else {
            $cancel_url = $urlHost . 'feed';
        }
        
        if($transaction->type == 'deposit') {
            // Incrementa el amount en un 10%
            $transaction->amount = $transaction->amount * 1.10;
        }

        $response = $gateway->purchase([
            'amount' => $transaction->amount,
            'currency' => config('paypal.currency'),
            'returnUrl' => $returnUrl,
            'cancelUrl' => $cancel_url,
        ])->send();

        if($response->isRedirect()) {
            $response->redirect();
        } else {
            return $response->getMessage();
        }
    } catch (Throwable $e){
        return $e->getMessage();
    }
}

Confirm sale:

public function completePurchase($PayerID, $paymentId, $amount)
{
    try {
        Log::info("Pre Complte Purchase");
        $response = $this->gateway->completePurchase([
            'payer_id' => $PayerID,
            'transactionReference' => $paymentId,
            'amount' => $amount,
            'currency' => env('PAYPAL_CURRENCY'),
        ])->send();
        Log::info("Post Complte Purchase");
        if ($response->isSuccessful()) {
            Log::info('Payment completed successfully: ' . json_encode($response->getData()));
        } else {
            Log::error('Payment failed: ' . $response->getMessage());
        }

        return $response;
    } catch (Throwable $e){
        return $e->getMessage();
    }
}

And this is the code that is in the success function, in the confirm route

 public function success (Request $request)
{
    $transaction = Transaction::find($request->transaction_id);

    Log::info("Request All");
    Log::info($request->all());
    $response = $this->completePurchase($request->PayerID, $request->paymentId, $request->amount);

    if ($response instanceof OmnipayCommonMessageResponseInterface && $response->isSuccessful()) {
        // El pago se completó con éxito
        Log::info('Payment completed successfully.');
       
    } else {
        // El pago falló
        Log::error('Payment failed or an error occurred.');
        // Actualizar el estado de la transacción a 'declined'
        $transaction->status = Transaction::DECLINED_STATUS;
        $transaction->save();

        if($transaction->type === Transaction::ROULETTE) {
            // Redirigir al usuario a la página de error
            return redirect()->route('roulette.show', ['username' => rawurlencode(User::find($transaction->recipient_user_id)->username), 'roulette_id' => $transaction->roulette_id])
                             ->with('error', __('Payment failed, please try again.'));
        } else if ($transaction->type === Transaction::TIP_TYPE) {
            // Redirigir al usuario a la página de error
            return redirect()->route('profile', ['username' => rawurlencode(User::find($transaction->recipient_user_id)->username)])
                             ->with('error', __('Payment failed, please try again.'));
        } else {
            // Redirigir al usuario a la página de error
            return redirect()->route('feed')->with('error', __('Payment failed, please try again.'));
        }
    }

Here: