Continuously search for a node and adjust its permissions in a recursive manner

Looking at the tree data structure I have:

type DataType = {
  id: string;
  access: 'view' | 'none';
  isDisabled: boolean;
  children: DataType[];
};

export const Data: DataType = {
  id: '1',
  access: 'view',
  isDisabled: false,
  children: [
    {
      id: '2',
      access: 'view',
      isDisabled: false,
      children: [
        {
          id: '3',
          access: 'view',
          isDisabled: false,
          children: [],
        },
      ],
    },
    {
      id: '4',
      access: 'view',
      isDisabled: false,
      children: [],
    },
    {
      id: '5',
      access: 'view',
      isDisabled: false,
      children: [],
    },
  ],
};

The goal is to update the isDisabled property when a node's access changes according to specific rules:

If access is set to 'view', then isDisabled remains false. If access is set to 'none', then isDisabled will be false for the current node but true for its children.

There are two functions available, however they are not functioning as intended:

// Function to find the desired node
const find = (
  data: DataType,
  selectedId: string,
  selectedAccess: 'view' | 'none'
) => {
  if (selectedId && selectedAccess) {
    if (data.id === selectedId) {
      data = changeAccess(data, selectedId, selectedAccess);
    } else {
      data.children.forEach((child) => find(child, selectedId, selectedAccess));
    }
  }
};

// Function to update access and isDisabled properties
const changeAccess = (
  data: DataType,
  selectedId: string,
  selectedAccess: 'view' | 'none'
): DataType => ({
  id: data.id,
  access: selectedAccess,
  isDisabled:
    data.id !== selectedId && selectedAccess !== 'view' ? true : false,
  children: data.children?.map((child) =>
    changeAccess(child, selectedId, selectedAccess)
  ),
});

When calling the find function with:

find(Data, '2', 'none');

The resulting updated data would be:

const DataAfter: DataType = {
  id: '1',
  access: 'view',
  isDisabled: false,
  children: [
    {
      id: '2',
      access: 'none',
      isDisabled: false,
      children: [
        {
          id: '3',
          access: 'none',
          isDisabled: true,
          children: [],
        },
      ],
    },
    {
      id: '4',
      access: 'view',
      isDisabled: false,
      children: [
        {
          id: '5',
          access: 'view',
          isDisabled: false,
          children: [],
        },
      ],
    },
  ],
};

Subsequent calls to find would further update the tree structure accordingly based on the provided rules.

If there are any insights or suggestions on how to improve these functions, it would be greatly appreciated.

I am still learning about recursion and tree data structures, and looking to enhance my understanding through practical exercises like this one.

Answer №1

Here is the code snippet:

data = modifyAccess(data, selectedId, selectedAccess)

When you use this line of code, a new object will be assigned to the data variable instead of mutating the original data. This means that the previous reference to data is discarded, and the caller does not see the updated object due to JavaScript's lack of call-by-reference behavior.

If your goal is to actually mutate the existing data structure, the modifyAccess function should directly modify it instead of returning a new object:

const update = (
  data: DataType,
  selectedId: string,
  selectedAccess: 'view' | 'none'
) => {
  if (selectedId && selectedAccess) {
    if (data.id === selectedId) {
      modifyAccess(data, selectedId, selectedAccess); // No return value
    } else {
      data.children.forEach((child) => update(child, selectedId, selectedAccess));
    }
  }
};

const modifyAccess = (
  data: DataType,
  selectedId: string,
  selectedAccess: 'view' | 'none'
) => Object.assign(data, { // Mutate `data`
  access: selectedAccess,
  isDisabled:
    data.id !== selectedId && selectedAccess !== 'view', // already boolean
  children: data.children?.map((child) =>
    modifyAccess(child, selectedId, selectedAccess)
  ),
});

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

Tips for ensuring that a JavaScript program does not get blocked by other API calls

My JavaScript API currently has limitations that prevent other APIs from being called or allowing the API to call itself while running. The API involves sleeping for a specific duration, during which I would like other API calls to be made as well. I have ...

Is there a way to keep a section of an animated class in place?

My website features an animated retractable menu bar with two separate menus. Clicking on one icon activates a sliding motion to reveal that particular menu while causing the second menu to retract in a similar fashion. To achieve a smooth transition effec ...

javascript functionality may be affected in Internet Explorer and Firefox following the upgrade to jquery version 1.8.3

After upgrading to jquery 1.8.3 from jquery 1.7 (where everything was functioning properly in all browsers), I added a javascript plugin that specifically requires jquery 1.8.2 or 1.8.3 Unfortunately, the image resizing functionality of this javascript is ...

unable to use ref to scroll to bottom

Can someone explain to me why the scroll to bottom feature using ref is not functioning properly in my code below? class myComponent extends Component { componentDidMount() { console.log('test') // it did triggered this.cont ...

Is there a way to modify the parent component's state and pass it down to the child component as a prop efficiently?

I am facing an issue with a parent component that sets the score counter and passes it to the child component. There is a function in the parent component called resetBoard() which should reset the score counter back to 0 when triggered by a button click ...

Where to Locate a String Excluding <a> Tags?

I'm in the process of writing a JavaScript code that will scan an HTML document and identify all occurrences of a specific keyword that are NOT contained within a link, meaning not under an <a> tag. To illustrate this, let's examine the fol ...

Support for BigInt is not available in TypeScript version 3.5.*

It seems that TypeScript has supported BigInt since version 3.2, and my project is using TypeScript 3.5. Despite not explicitly declaring any variables as BigInt, I recently integrated a package called BufferUtility from https://github.com/Pharuxtan/Buffer ...

"Unleashing the Power of AngularJS: Implementing a Global Error Handler to Display and

When building my website, I have multiple Angular apps that require a global error handler to track and display alerts for errors with codes like 500 and 401. Here is what I have so far: In order to create a global error handler module, I've set up t ...

Creating a React functional component that updates state when a specific window breakpoint is reached

Having an issue with my code when it hits the 960px breakpoint. Instead of triggering once, it's firing multiple times causing unexpected behavior. Can someone help me troubleshoot this problem? const mediaQuery = '(max-width: 960px)'; con ...

In this JavaScript code, learn how to organize an array based on its numerical property

What is the best way to organize an array based on the 'num' property in this JavaScript array? var data = [{ 005: { `num`: 1360487}, 047: { `num`: 2519472}, 061: { `num`: 1559115}, 081: { `num`: 2232710}, 085: { `num`: 54956 ...

Dynamic user group system that leverages Ajax technology for seamless integration with an HTML interface, powered by PHP and

I am new to this, so please forgive my lack of knowledge. Currently, I am in the process of creating an Ajax-driven web application for managing user contact groups. This application allows users to store contacts based on assigned groups. Once a user con ...

Repairing the 'Uncaught TypeError: Cannot read property 'split' of undefined' bug in a Prestashop Module

Help! I'm encountering an issue with a Prestashop module, and the developer is unresponsive. Can anyone shed light on why I am seeing this error in the console? Thank you so much in advance! admin.js:57 Uncaught TypeError: Cannot read property ' ...

Deploying an Angular 2 application using SystemJS and Gulp can sometimes feel cumbersome due to its

Although I have experience developing with Angular, I recently started working with Angular 2. After completing the quickstarter tutorial, I attempted to deploy the finished application on a server in production mode. My lack of experience with SystemJS a ...

Having trouble with passing post data from jQuery ajax to a php page?

Attempting to retrieve post data using an alert() function, but encountering an issue where the data is not being passed to the PHP page. The result always shows {"success":false,"result":0} The goal is to transmit a password to the PHP page, hash it usin ...

What is the process for connecting a date/time form control?

My code seems to only be working for the 'title' element, while the 'docdatetime' control remains blank. Can anyone spot what I'm doing wrong? //template =================================================== <div class="form-grou ...

Using jQuery AJAX, the value of a server-side control (textbox) can be easily set

After working with the code below, I noticed that I can only set the value received from an ajax call if I am using HTML controls like buttons and text boxes. If I try to use asp server controls such as a button, the ajax call does not return any output, e ...

Exploring the possibilities of integrating jQuery into Firefox extensions

Can someone provide guidance on effectively implementing jQuery within a Firefox extension? My research has not yielded any up-to-date methods that address the latest version of jQuery, and I am aware that directly including it via script tag may lead to c ...

Redux: triggering a dispatch when a component or function is initialized

I'm facing a challenge where I need to update a state only when a specific functional component is initialized. My initial approach was to try something like this: export default function SalesFeedPage(){ const {salesFeed} = useSelector((state) => ...

Exploring Head-Linked/Off-center View in Three.js

I'm attempting to create a permanent head-coupled perspective without relying on the full headtrackr library. My head will remain stationary, but it will not be directly facing the screen. For those interested, I have a small demonstration available ...

When a link is clicked, the text within an input field

Seeking a solution for inserting a value into an input when clicking a link, with the inserted value being the name of the clicked link. I am unsure how to achieve this. Can anyone provide guidance? The solution can involve jQuery, JavaScript, PHP, or any ...