初心者のプログラミング日記

プログラミング初心者の日記

プログラミングに関することを書いていきます。

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をつかっています。
これで簡単なツリー表示ができました。
f:id:nasubiFX:20200628174345p:plain