1

I have an infinitely deep folders tree-array. Each folder have a "hasPermission" boolean. What I want to achieve is when a parent folder's (that can be located anywhere in the tree) "hasPermission" changes, all it's children "hasPermission" will also change - of course, the grandparent folders "hasPermission" will not change.

For example, in the folder tree below. If folderId: '2.1' changes permission, folderId: '3.1' will also change; the others will stay the same.

const example = [
  {
    folderId: '1',
    hasPermission: false,
    children: [
      {
        folderId: '2.1',
        hasPermission: false,
        children: [
          {
            folderId: '3.1',
            hasPermission: false,
            children: [],
          },
        ],
      },
      {
        folderId: '2.2',
        hasPermission: false,
        children: [],
      },
    ],
  },
];

This function changes the "hasPermission" recursively.

  const changeChildrenPermission = (
    folders
  ) => {
    return folders.map(
      ({ id, children, hasPermission }) => ({
        id,
        hasPermission: (hasPermission === false && true) || false,
        children: changeChildrenPermission(children),
      })
    );
  };

Here is what I have so far, I'm trying to look up the tree for the selectedId, if it matches, then call the "changeChildrenPermission" function.

  const setPermissionChange = (
    folders,
    selectedId
  ) => {
    const a = folders.map((folder) => {
      if (folder.id === selectedId) {
       return {
          id: folder.folderId,
          hasPermission: (hasPermission === false && true) || false,
          children: changeChildrenPermission(folder.children),
        };
    });
  };

Not sure what to do afterwards.

4
  • Could you give a complete reproducible example? Commented Aug 18, 2021 at 8:29
  • sure thing, I'll update it with expected outcome Commented Aug 18, 2021 at 9:07
  • I think "2.1" should be "1.1.1" Commented Aug 18, 2021 at 9:19
  • 1
    Ahh yes, thank you kol, I've updated it. And thank you for the solution below :) Commented Aug 18, 2021 at 9:26

1 Answer 1

0

// visitFolders: Walks the folder tree recursively and calls visitFolder for every folder.
// - If visitFolder returns true for a folder, the walk stops immediately.
// - If you want to visit all folders, visitFolder should return false.
//   (Returning false can be omitted, because the default return value of functions is undefined, which is falsy.)
const visitFolders = (folders, visitFolder) => {
  for (let folder of folders) {
    if (visitFolder(folder) || visitFolders(folder.children, visitFolder)) {
      return true;
    }
  }
  return false;
};

const findFolderById = (folders, id) => {
  let folderWithId = null;
  visitFolders(folders, folder => {
    if (folder.id === id) {
      folderWithId = folder;
      return true;
    }
    return false;
  });
  return folderWithId;
};

const setFolderPermission = (folder, hasPermission) => {
  visitFolders([folder], folder => {
    folder.hasPermission = hasPermission;
    return false;
  });
};

const folders = [
  {
    id: "1",
    hasPermission: true,
    children: [
      {
        id: "1.1",
        hasPermission: true,
        children: []
      },
      {
        id: "1.2",
        hasPermission: true,
        children: [
          {
            id: "1.2.1",
            hasPermission: true,
            children: []
          },
          {
            id: "1.2.2",
            hasPermission: true,
            children: []
          }
        ]
      },
      {
        id: "1.3",
        hasPermission: true,
        children: []
      },
      {
        id: "1.4",
        hasPermission: true,
        children: []
      }
    ]
  },
  {
    id: "2",
    hasPermission: true,
    children: [
      {
        id: "2.1",
        hasPermission: true,
        children: []
      },
      {
        id: "2.2",
        hasPermission: true,
        children: []
      }
    ]
  }
];

const folder = findFolderById(folders, "1.2");
if (folder !== null) {
  setFolderPermission(folder, false);
}
visitFolders(folders, folder => {
  console.log(folder.id, folder.hasPermission);
  return false;
});

Sign up to request clarification or add additional context in comments.

4 Comments

Can I ask, for function "const visitFolders = (folders, visitFolder)", how would I type "visitFolder"? And when you use it in: const findFolderById = (folders, id) => { let folderWithId = null; visitFolders(folders, folder => { where is this "folder" variable coming from?
I added an explanation before visitFolders. It's a helper function which recursively walks the folder tree, that is, it visits every folder, and calls visitFolder on every folder. The visitFolder function can do anything you want.
Hi Koi, sorry to bother you again, I want to use this in React with const [folders, setFolders] = useState(initialFoldersData); when I try to setFolders with folder, it rerenders too many times. visitFolders(folders, folder => { setFolders(folder) return false; });
Search for recursive tree rendering in React: coderrocketfuel.com/article/…, stackoverflow.com/questions/60566919/… etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.