Reactでコンポーネントの再帰利用
使うファイル
index.tsx
App.tsx
TreeView.tsx
index.tsx
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import * as serviceWorker from './serviceWorker'; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode> document.getElementById('root') ); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA serviceWorker.unregister();
変更なし
App.tsx
import React, { useState } from "react"; import './App.css'; import TreeView from './TreeView'; type Trees = { name: string children: any[] }[] const App: React.FC = () => { const [open, setOpen] = useState<boolean>(false); const [trees, setTrees] = useState<Trees>( [ { name: "parent", children: [ { name: "child1" }, { name: "child2" }, { name: "child3", children: [ { name: "child3-1" }, { name: "child3-2" }, { name: "child3-3", children: [ { name: "child3-3-1" } ] } ] }, { name: "child4" } ] } ] ) function isOpen() { setOpen(!open) } const style = { cursor: "pointer", transform: (!open ? "" : "rotate(90deg)"), } return ( <div className="root"> <ul> <li onClick={isOpen}> <i className="fas fa-chevron-right" onClick={isOpen} style={style}></i> <label>{trees[0].name}</label> </li> {open && <TreeView trees={trees[0].children} /> } </ul> </div> ) } export default App;
まだ連想配列の型定義がよくわからなくてanyにしています。
わかったら直します。
TreeView.tsx
import React, { useState, useEffect, useRef } from "react"; import './TreeView.css' type Props = { trees: any[] } const TreeView: React.FC<Props> = ({ trees }) => { const [open, setOpen] = useState(false); function isOpen() { setOpen(!open) } const style = { cursor: "pointer", transform: (!open ? "" : "rotate(90deg)"), } return ( <div className="treeview"> {trees.map(tree => { if (Array.isArray(tree.children)) { return ( <div className="child" > <li onClick={isOpen}> <i className="fas fa-chevron-right" onClick={isOpen} style={style}></i> <label>{tree.name}</label> </li> {open && <ul> <TreeView trees={tree.children} /> //ここで再帰利用 </ul> } </div> ) } return <li>{tree.name}</li> })} </div> ) } export default TreeView;
最初refを使わずにやったら全部閉じてしまったのでrefをつかっています。
これで簡単なツリー表示ができました。