0

I want to display inside a material TreeView the content of a directory while parsing it.

Here's what I have for now:

const getElement = (path: string) => {
  fs.readdir(path, (_: any, elements: any) => {
    elements.forEach((element: string) => {
    let elementPath: string = libpath.join(path, element)
    if(fs.lstatSync(elementPath).isFile()) {
      return (
        <TreeItem nodeId="" label={element}/> //I'll take care of nodeId later
      )
    } else {
      return (
        <TreeItem nodeId="" label={element}>
          {getElement(elementPath)}
        </TreeItem>
      )
    }
  })
})}

export default class DataTreeView extends React.Component {
  render() {
    return (
      <TreeView
        defaultCollapseIcon={<ExpandMoreIcon />}
        defaultExpandIcon={<ChevronRightIcon />}
      >
        {getElement(window.process.env.HOME)} //return $HOME env var, will get this value from props later
      </TreeView>
    );
  }
}

It feels like I'm almost there but I keep getting this error "Type 'void' is not assignable to type 'ReactNode'." for the getElement function which I don't understand because it return a ReactNode in every case. Is the asynchronous part of fs.readdir is the problem here ?

Thanks for your help

CharlesR
  • 53
  • 7
  • Does this answer your question? [How to return value from an asynchronous callback function?](https://stackoverflow.com/questions/6847697/how-to-return-value-from-an-asynchronous-callback-function) – Andy Ray Jun 03 '21 at 16:10
  • @AndyRay not really, I can add a callback to getElement but what would I do inside ? I want the TreeItem to be created dynamically so I don't quite know how to handle this problem – CharlesR Jun 03 '21 at 16:27
  • Your `getElement` function doesn't return anything. It eventually runs a callback which runs long after `getElement` has finished. You probably want to collect your tree structure first, and once that completes, then do your react rendering. – Andy Ray Jun 03 '21 at 16:29

1 Answers1

2

Firstly you forgot to return your created nodes this is why you found the void problem, secondly, you have to use a synchronous version of readdir.

  const getElement = (path: string) => {
  const elements = fs.readdirSync(path)
  return elements.map((element: string) => {
    let elementPath: string = libpath.join(path, element)
    if (fs.lstatSync(elementPath).isFile()) {
      return (
        <TreeItem nodeId="" label={element} /> //I'll take care of nodeId later
      )
    } else {
      return (
        <TreeItem nodeId="" label={element}>
          {getElement(elementPath)}
        </TreeItem>
      )
    }
  })
}

export default class DataTreeView extends React.Component {
  render() {
    return (
      <TreeView
        defaultCollapseIcon={<ExpandMoreIcon />}
        defaultExpandIcon={<ChevronRightIcon />}
      >
        {getElement(window.process.env.HOME)} //return $HOME env var, will get
        this value from props later
      </TreeView>
    )
  }
}
Soufiane Boutahlil
  • 2,554
  • 1
  • 7
  • 13
  • Thanks @boutahlilsoufiane this works!! My bad I didn't catch the read dir sync and the return with the map function! – CharlesR Jun 03 '21 at 17:20