
Posted on • Originally published atanuraghazra.github.io
Building A React Folder Tree Component
Photo byJohann Siemens on Unsplash
This post was originally published onmy personal site
Hey folks! I hope you are doing fine in this pandemic situation, Today we will be creating a Folder Tree Component in
Reactjs from scratch.
Designing the API
Before creating any type of component in reactjs you should 1st design how the API would look like and then write the
necessary code to make it work.
Our Folder Tree Component will have two APIs
- Declarative
- Imperative
At first we will tackle the Declarative API which is really simple to create,
and in the second section we will do the Imperative API with recursive components.
Declarative API
The declarative API would look something like this :-
importTreefrom'./Tree';constApp=()=>{return(<div><Tree><Tree.Foldername="src"><Tree.Foldername="Components"><Tree.Filename="Modal.js"/><Tree.Filename="Modal.css"/></Tree.Folder><Tree.Filename="index.js"/><Tree.Filename="index.html"/></Tree.Folder><Tree.Filename="package.json"/></Tree></div>);};
As you can see we will have total of three components to work with
- <Tree /> (the root)
- <Tree.Folder /> (it will be collapsible)
- <Tree.File />
Imperative API
Declarative APIs are simple & easier for users to structure the Tree, but in real world scenarios we will have a JSON
Object representing the Folder Tree and we need to render that with the Imperative API.
importTreefrom'./Tree';conststructure=[{type:"folder",name:"src",childrens:[{type:"folder",name:"Components",childrens:[{type:"file",name:"Modal.js"},{type:"file",name:"Modal.css"}]},{type:"file",name:"index.js"},{type:"file",name:"index.html"}]},{type:"file",name:"package.json"}];constApp=()=>{return(<div><Treedata={structure}/></div>);};
As you can see we have a JSON representation of the same tree we have in our declarative API.
Its an Array of Objects and each object has three properties
- name
- type (defines if its a Folder or File)
- childrens (array of nested Files & Folders)
And we just passed thisstructure
to our component which will handle the rendering, we will cover the
Imperative API later in the post but let us first finish our Declarative API
The Tree Component
Lets first install styled-components for styling our Components.
npminstallstyled-components
Our Tree component will be very simple it will only have some basic styling, it is so simple i don't even have to
explain it.
constStyledTree=styled.div` line-height: 1.5;`;constTree=({children})=>{return<StyledTree>{children}</StyledTree>;};
The File Component
In our File component we will also have a File Icon with some basic styling.
Lets installreact-icons and import our File Icon
npminstallreact-icons
import{AiOutlineFile}from'react-icons/ai';constStyledFile=styled.div` padding-left: 20px; display: flex; align-items: center; span { margin-left: 5px; }`;constFile=({name})=>{return(<StyledFile><AiOutlineFile/><span>{name}</span></StyledFile>);};
We have a 20px padding left to push the Component to the right a little bit, and display flex properties to align the
icon & span correctly.
That's fine but that generic file icon does not look good, does it? lets change that.
We will make a map of extension icons and depending on the file extension we will give the file appropriate icon.
import{DiJavascript1,DiCss3Full,DiHtml5,DiReact}from'react-icons/di';constFILE_ICONS={js:<DiJavascript1/>,css:<DiCss3Full/>,html:<DiHtml5/>,jsx:<DiReact/>,};exportdefaultFILE_ICONS;
And in the File component we will extract the extension from the name of the file and use that to render the icon
importFILE_ICONSfrom'./FileIcons';constFile=({name})=>{// get the extensionletext=name.split('.')[1];return(<StyledFile>{/* render the extension or fallback to generic file icon */}{FILE_ICONS[ext]||<AiOutlineFile/>}<span>{name}</span></StyledFile>);};
It would look something like this.
Hooray our File component is done, let's move on to Folder component
The Folder Component
In the Folder component we will have
- folder title
- collapsible component
- Nested childrens of File/Folder components
Initially our Folder component is very simple, just the title and childrens.
btw if you don't know what that
children
prop is then here's some resources
A quick intro to React’s props.children
A deep dive into children in React
import{AiOutlineFolder}from'react-icons/ai';constStyledFolder=styled.div` padding-left: 20px; .folder--label { display: flex; align-items: center; span { margin-left: 5px; } }`;constFolder=({name,children})=>{return(<StyledFolder><divclassName="folder--label"><AiOutlineFolder/><span>{name}</span></div><div>{children}</div></StyledFolder>);};
And thats it, thats all we need for our Folder component but we also wanted the folders to be collapsible so lets add
that next.
To add the collapse feature we will add a Styled component and also add local state to keep track ofisOpen
state of our component.
constStyledFolder=styled.div` padding-left: 20px; .folder--label { display: flex; align-items: center; span { margin-left: 5px; } }`;constCollapsible=styled.div` /* set the height depending on isOpen prop */ height:${p=>(p.isOpen?'auto':'0')}; /* hide the excess content */ overflow: hidden;`;constFolder=({name,children})=>{const[isOpen,setIsOpen]=useState(false);consthandleToggle=e=>{e.preventDefault();setIsOpen(!isOpen);};return(<StyledFolder><divclassName="folder--label"onClick={handleToggle}><AiOutlineFolder/><span>{name}</span></div><CollapsibleisOpen={isOpen}>{children}</Collapsible></StyledFolder>);};
There we go! Our Folder Component is done, Yey!
Finalizing Tree Component
As you've noticed in our Declerative API design, we have & components we can just assign
the File & Folder component to our Tree's static methods.
constTree=({children})=>{return<StyledTree>{children}</StyledTree>;};Tree.File=File;Tree.Folder=Folder;////////// DONE! Lets try it outimportTreefrom'./Tree';constApp=()=>{return(<div><Tree><Tree.Foldername="src"><Tree.Foldername="Components"><Tree.Filename="Modal.js"/><Tree.Filename="Modal.css"/></Tree.Folder><Tree.Filename="index.js"/><Tree.Filename="index.html"/></Tree.Folder><Tree.Filename="package.json"/></Tree></div>);};
If we run the code now we will have a working React Folder Tree Component! Congrats 🎉🎉
Declerative Demo
Imperative API
OKAY! we are done with the Declerative API now lets work on the Imperative API.
To create the Imperative API we need recursion!
If you are not familiar with recursion then check out some resources
A Quick Intro to Recursion in Javascript
Intro to Recursion in JS
In our component we accept thedata
props and added anisImperative
flag.
If we have the data prop and not the children that means the user is using the imperative api, and depending on that
variable we will be rendering the tree.
constTree=({data,children})=>{constisImperative=data&&!children;return<StyledTree>{isImperative?<TreeRecursivedata={data}/>:children}</StyledTree>;};
As you've noticed we also added a new component called<TreeRecursive />
which will recursively look through the JSON
structure and render those nested files/folders, Lets implement it.
constTreeRecursive=({data})=>{// loop through the datareturndata.map(item=>{// if its a file render <File />if(item.type==='file'){return<Filename={item.name}/>;}// if its a folder render <Folder />if(item.type==='folder'){return(<Foldername={item.name}>{/* Call the <TreeRecursive /> component with the current item.childrens */}<TreeRecursivedata={item.childrens}/></Folder>);}});};
Believe it or not, we are DONE! 🎉🎉 Run the code and see the magic!
Imperative Demo
Phew! That was amazing isn't it? if you made it this far, give yourself a tap on the shoulder because you just built a React Folder Tree Component!
Now for those who are looking for some more fun try to implement these features on your own :-
- File/Folder Rename Support
- File/Folder Creation Support
- File/Folder Deletion Support
- Save folder structure to localStorage Support
Foot notes
- Check out myreact-folder-tree component with full CRUD support.
- CodeSandboxLink for Declerative API
- CodeSandboxLink for Imperative API
- A quick intro to React’s props.children
- A deep dive into children in React
- A Quick Intro to Recursion in Javascript
- Intro to Recursion in JS
Thanks for reading the post, i hope you learned something and enjoyed it.
Stay safe, stay home!
Bye have a nice day!
Top comments(4)

- Email
- LocationAmman, Jordan
- EducationBachelor's in Engineering
- WorkPrincipal Engineer at Wiley
- Joined
Very informative big like

- LocationKolkata, West Bengal, India
- Joined
Thank you, I'm glad you liked it. 🤗


- LocationKolkata, West Bengal, India
- Joined
Here, you can check out my example. It has full CRUD functionality.github.com/anuraghazra/react-folde...
For further actions, you may consider blocking this person and/orreporting abuse