Is it possible for me to incorporate additional functionalities to the scanning process?

I am facing an issue: "How to create a rectangle on mouse down, resize it while moving, and finalize the shape on mouse up". I attempted to solve this using rxjs, but it doesn't seem like the optimal solution:

import { scan, mergeMap, takeUntil, fromEvent } from 'rxjs';

const mouseDown$ = fromEvent(document, 'mousedown');
const mouseUp$ = fromEvent(document, 'mouseup');
const mouseMove$ = fromEvent(document, 'mousemove');

function createRectangle() {
  const rectangle = document.createElement('DIV');
  rectangle.setAttribute('style', 'position: absolute; border: 1px solid red;');
  document.body.appendChild(rectangle);
  return rectangle;
}

mouseDown$
  .pipe(
    mergeMap(() => {
      return mouseMove$.pipe(
        takeUntil(mouseUp$),
        scan((rectangle, e) => {
          if (!rectangle) {
            let x = null;
            x = createRectangle();
            x.style.top = `${e.clientY}px`;
            x.style.left = `${e.clientX}px`;
            return x;
          } else {
            rectangle.style.bottom = `${e.clientY}px`;
            rectangle.style.right = `${e.clientX}px`;
          }
          return rectangle;
        }, null)
      );
    })
  )
  .subscribe(() => {});

The issue lies in the side-effects being part of the "scan" method. Do you have a more efficient solution for this problem?

Answer №1

To prevent any potential inner pipe side effects, it is recommended to divide your logic into two separate Observables/Subscriptions:

Create New Node Observable

let node = null

const createNewNode$ = mouseDown$.pipe(
  switchMapTo(mouseMove$.pipe(
    takeUntil(mouseUp$),
    take(1)
  ))
)

createNewNode$.subscribe(createNewNode)

function createNewNode(e: MouseEvent) {
  const newNode = document.createElement('DIV');
  newNode.setAttribute('style', 'position: absolute; border: 1px solid red;');
  document.body.appendChild(newNode);
  x.style.top = `${e.clientY}px`;
  x.style.left = `${e.clientX}px`;
  return newNode;
}

Update Node Observable

const updateNode$ = mouseDown$.pipe(
  switchMapTo(mouseMove$.pipe(
    takeUntil(mouseUp$),
    skip(1)
  ))
)

updateNode$.subscribe(updateNode(node))

function updateNode(existingNode: Node) {
  return function(e: MouseEvent) {
    existingNode.style.bottom = `${e.clientY}px`;
    existingNode.style.right = `${e.clientX}px`;
  }
}

I don't have a preference between the above method and your initial solution - they are essentially equivalent in my opinion. This just offers an alternative approach to potentially mitigating side effects. Different perspectives exist on when and why to avoid side effects. Personally, I strive to minimize them, but sometimes it may not be practical (or I may simply lack a better solution).

I once raised a question regarding when-should-i-create-a-new-subscription-for-a-specific-side-effect. The response provides insights into the usefulness of avoiding side effects under specific circumstances.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to showcase the output of the <div id="height"> on the height of the rectangle?

My Current Project Currently, I am in the process of developing a picture framing calculator using a combination of HTML, CSS, and JavaScript. Functionality of the Calculator For this calculator, users will input values such as: Frame Width (wf): 16 ...

Utilizing AngularJS and Node.js to update MongoDB

Looking for a solution to update my MongoDB using Node.js and AngularJS within the front-end of my application. The code I currently have is causing an error stating `TypeError: Cannot read property 'put' of undefined. Here is my AngularJS contr ...

Tips for efficiently sending multiple ajax requests

Seeking help with my ajax knowledge. Currently, I have a function that is supposed to insert multiple items into an SQL database using a PHP page. However, it seems to only be inserting the last item entered. Here's the code snippet: function submitI ...

Is it possible to modify the sizes parameter of the GPUComputationRenderer?

Currently, I am utilizing gpuCompute = new GPUComputationRenderer( sizeX, sizeY, renderer ); for texture purposes. I am looking to update the values of sizeX and sizeY within this code snippet. However, after searching through the library, I have not been ...

Integrating VueJs into a pre-existing .net core 5 project

I am currently working on a .net core solution that consists of 9 different projects including api, dto, data, service, etc. I now have the requirement to incorporate a project that utilizes the Vue.js framework for the frontend within this existing .net ...

Communicate through PHP and JavaScript chat to display HTML content in the chat window

I have been attempting to display HTML output in the chat window but instead, it is showing the HTML code. Here are the two files involved in the chat system: chat.js `function chatHeartbeat(){ var itemsfound = 0; if (windowFocus == false) { var ...

How to assign a value to an array within a form in Angular 8

I'm facing an issue with my Angular 8 edit form that utilizes a form array. When I navigate to the page, the form array is not populated with values as expected. Can anyone help me identify and solve this problem? ngOnInit(): void { // Fetc ...

Implementing a secure route in Next.js by utilizing a JWT token obtained from a customized backend system

Currently, I am in the process of developing a full-stack application utilizing NestJS for the backend and Next.js for the frontend. Within my NestJS backend, I have implemented stateless authentication using jwt and passport. My next goal is to establis ...

Using React Higher Order Components with several different components

Is it possible to create a React HOC that can accept two components instead of just one wrapped component and toggle between them? For instance, in the code snippet below, rather than having <h3>component one</h3> and <h3>component two< ...

Prevent the selection of Single Origin and House Blend options once the user opts for Espresso

<td> <select class="type"> <option value="Espresso">Espresso</option> <option value="" class="">Cappuccino</option> <opti ...

Using a Hook inside a React function is not possible

I encountered an error message known as the "invalid hook call error" while using the useEffect hook in my code. According to the documentation, this issue usually arises due to either a version mismatch or incorrect function calls. Could someone kindly r ...

Invoke the parent method within the child application

I have a checkbox on the child app controller. When the user clicks it, I need to call a method from the parent controller: Parent app controller: <div ng-controller="ParentCntr as parentCntr"> <child-app></child-app> </div> C ...

What is the best way to set the first radio button as the default selection in Material UI?

The challenge I am facing involves a set of radio buttons representing dates from today to 30 days in the future. When a radio button is selected or active, it changes the background color. However, I would like the default selection to be the first radio ...

Join a subscription and remain subscribed in sequential order

Within the code below, there is a nested subscribe function. It takes a schedule_id and retrieves questions based on that schedule_id. The functionality works correctly, but the order in which getQuestion() is executed is not guaranteed. Schedule IDs: 111, ...

Update the content within an HTML tag using JavaScript

I've been attempting to update the text within the li tag using plain javascript. The structure of the HTML will remain consistent: <section id="sidebar-right" class="sidebar-menu sidebar-right sidebar-open"> <div class="cart-sidebar-wrap" ...

What are the steps to successfully deploy a static website created with Next.js on Vercel?

Using the Next.js static site generator, I created a simple static site that I now want to deploy on Vercel. However, I keep encountering an error during the build process. While I have successfully deployed this site on other static hosting platforms befo ...

Navigating through multiple pages with React Native stack navigation

I'm currently in the process of developing a react native app and I'm facing some confusion with regards to page navigation. It appears that there is a glitch in the navigation flow, causing it to skip a page. <NavigationContainer> ...

Mastering the art of managing promises within nested loops

Embarking on my Promise journey, I find myself faced with a scenario where a list of objects within another list of objects needs to be updated based on responses from an external API. I've attempted to simulate the scenario below. The code snippet f ...

The issue of dynamic select not sending the POST data

Having an issue with a form where the selected country and city are not being posted correctly. Despite different names in the form and php mailer script, both selections are coming through as the country. Here's the form: <select style="width: 6 ...

Definition of a Typescript Global.d.ts module for a function that is nested within another function

Simply put, I have a npm module that exports a function along with another function attached to it: // @mycompany/module ... const someTool = (options) => { // do some cool stuff }; someTool.canUseFeature1 = () => { return canUseSomeFeature1(); ...