REACTJS - 将 class 组件转换为功能组件

REACTJ - convert class component to functionnal component

我是 React 新手,我正在尝试将这个基于 class 的组件转换为功能组件,但我收到状态错误,请问我该如何转换? 这是我的组件:)

sandbox link

谢谢

import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Tree } from 'antd';
const treeData = [
  {
    title: '0-0',
    key: '0-0',
    children: [
      {
        title: '0-0-0',
        key: '0-0-0',
        children: [
          {
            title: '0-0-0-0',
            key: '0-0-0-0',
          },
          {
            title: '0-0-0-1',
            key: '0-0-0-1',
          },
          {
            title: '0-0-0-2',
            key: '0-0-0-2',
          },
        ],
      },
      {
        title: '0-0-1',
        key: '0-0-1',
        children: [
          {
            title: '0-0-1-0',
            key: '0-0-1-0',
          },
          {
            title: '0-0-1-1',
            key: '0-0-1-1',
          },
          {
            title: '0-0-1-2',
            key: '0-0-1-2',
          },
        ],
      },
      {
        title: '0-0-2',
        key: '0-0-2',
      },
    ],
  },
  {
    title: '0-1',
    key: '0-1',
    children: [
      {
        title: '0-1-0-0',
        key: '0-1-0-0',
      },
      {
        title: '0-1-0-1',
        key: '0-1-0-1',
      },
      {
        title: '0-1-0-2',
        key: '0-1-0-2',
      },
    ],
  },
  {
    title: '0-2',
    key: '0-2',
  },
];

const Demo = () => {
  const [expandedKeys, setExpandedKeys] = useState(['0-0-0', '0-0-1']);
  const [checkedKeys, setCheckedKeys] = useState(['0-0-0']);
  const [selectedKeys, setSelectedKeys] = useState([]);
  const [autoExpandParent, setAutoExpandParent] = useState(true);

  const onExpand = (expandedKeysValue) => {
    console.log('onExpand', expandedKeysValue); // if not set autoExpandParent to false, if children expanded, parent can not collapse.
    // or, you can remove all expanded children keys.

    setExpandedKeys(expandedKeysValue);
    setAutoExpandParent(false);
  };

  const onCheck = (checkedKeysValue) => {
    console.log('onCheck', checkedKeysValue);
    setCheckedKeys(checkedKeysValue);
  };

  const onSelect = (selectedKeysValue, info) => {
    console.log('onSelect', info);
    setSelectedKeys(selectedKeysValue);
  };

  return (
    <Tree
      checkable
      onExpand={onExpand}
      expandedKeys={expandedKeys}
      autoExpandParent={autoExpandParent}
      onCheck={onCheck}
      checkedKeys={checkedKeys}
      onSelect={onSelect}
      selectedKeys={selectedKeys}
      treeData={treeData}
    />
  );
};

ReactDOM.render(<Demo />, document.getElementById('container'));

在此示例中,由于没有组件生命周期方法,因此非常简单。您可以只定义函数中的所有方法,return 组件。

function Demo() {
  const [state, setState] = React.useState({
    expandedKeys: [],
    autoExpandParent: true,
    checkedKeys: [],
    allCheckedKeys: [],
    selectedKeys: [],
    newTreeView: false,
    newTreeData: []
  });

  const onExpand = (expandedKeys) => {
    console.log("onExpand", expandedKeys);
    // if not set autoExpandParent to false, if children expanded, parent can not collapse.
    // or, you can remove all expanded children keys.
    setState({
      ...state,
      expandedKeys,
      autoExpandParent: false
    });
  };

  const onCheck = (checkedKeys, e) => {
    const allCheckedKeys = [...checkedKeys, ...e.halfCheckedKeys];
    console.log("onCheck", allCheckedKeys);

    console.log(createNewTreeData(treeData, allCheckedKeys));
    setState((prevState) => ({
      ...prevState,
      allCheckedKeys,
      checkedKeys
    }));
  };

  const onSelect = (selectedKeys, info) => {
    console.log("onSelect", info);
    setState({ ...state, selectedKeys });
  };

  const renderTreeNodes = (data) =>
    data.map((item) => {
      if (item.children) {
        return (
          <TreeNode title={item.title} key={item.key} dataRef={item}>
            {renderTreeNodes(item.children)}
          </TreeNode>
        );
      }
      return <TreeNode {...item} />;
    });

  const createTree = () => {
    setState((prevState) => ({
      ...prevState,
      newTreeView: true,
      newTreeData: createNewTreeData(treeData, prevState.allCheckedKeys)
    }));
  };

  return (
    <>
      <Tree
        checkable
        onExpand={onExpand}
        expandedKeys={state.expandedKeys}
        autoExpandParent={state.autoExpandParent}
        onCheck={onCheck}
        checkedKeys={state.checkedKeys}
        onSelect={onSelect}
        selectedKeys={state.selectedKeys}
      >
        {renderTreeNodes(treeData)}
      </Tree>
      <button onClick={createTree}>Validate</button>
      {state.newTreeView && <Tree>{renderTreeNodes(state.newTreeData)}</Tree>}
    </>
  );
}

我已经使用 ES6 箭头函数更新了代码,从而使代码比传统功能组件更短、更简单。

import React,{useState} from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Tree } from "antd";

const { TreeNode } = Tree;

const treeData = [
  {
    title: "0-0",
    key: "0-0",
    children: [
      {
        title: "0-0-0",
        key: "0-0-0",
        children: [
          { title: "0-0-0-0", key: "0-0-0-0" },
          { title: "0-0-0-1", key: "0-0-0-1" },
          { title: "0-0-0-2", key: "0-0-0-2" }
        ]
      },
      {
        title: "0-0-1",
        key: "0-0-1",
        children: [
          { title: "0-0-1-0", key: "0-0-1-0" },
          { title: "0-0-1-1", key: "0-0-1-1" },
          { title: "0-0-1-2", key: "0-0-1-2" }
        ]
      },
      {
        title: "0-0-2",
        key: "0-0-2"
      }
    ]
  },
  {
    title: "0-1",
    key: "0-1",
    children: [
      { title: "0-1-0-0", key: "0-1-0-0" },
      { title: "0-1-0-1", key: "0-1-0-1" },
      { title: "0-1-0-2", key: "0-1-0-2" }
    ]
  },
  {
    title: "0-2",
    key: "0-2"
  }
];

const createNewTreeData = (treeData, checkedKeys) => {
  return treeData.reduce((acc, treeDataItem) => {
    if (checkedKeys.includes(treeDataItem.key)) {
      if (treeDataItem.children) {
        acc.push({
          ...treeDataItem,
          children: createNewTreeData(treeDataItem.children, checkedKeys)
        });
      } else {
        acc.push(treeDataItem);
      }
    }

    return acc;
  }, []);
};

const Demo =()=> {
  const [state,setState] = useState({
    expandedKeys: [],
    autoExpandParent: true,
    checkedKeys: [],
    allCheckedKeys: [],
    selectedKeys: [],
    newTreeView: false,
    newTreeData: []
  });

  const onExpand = (expandedKeys) => {
    console.log("onExpand", expandedKeys);
    // if not set autoExpandParent to false, if children expanded, parent can not collapse.
    // or, you can remove all expanded children keys.
    setState({
      expandedKeys,
      autoExpandParent: false
    });
  };

 const onCheck = (checkedKeys, e) => {
    const allCheckedKeys = [...checkedKeys, ...e.halfCheckedKeys];
    console.log("onCheck", allCheckedKeys);

    console.log(createNewTreeData(treeData, allCheckedKeys));
    setState((prevState) => ({
      ...prevState,
      allCheckedKeys,
      checkedKeys
    }));
  };

  const onSelect = (selectedKeys, info) => {
    console.log("onSelect", info);
    setState({ selectedKeys });
  };

  const renderTreeNodes = (data) =>
    data.map((item) => {
      if (item.children) {
        return (
          <TreeNode title={item.title} key={item.key} dataRef={item}>
            {renderTreeNodes(item.children)}
          </TreeNode>
        );
      }
      return <TreeNode {...item} />;
    });

  const createTree = () => {
    setState((prevState) => ({
      ...prevState,
      newTreeView: true,
      newTreeData: createNewTreeData(treeData, prevState.allCheckedKeys)
    }));
  };

    return (
      <>
        <Tree
          checkable
          onExpand={onExpand}
          expandedKeys={state.expandedKeys}
          autoExpandParent={state.autoExpandParent}
          onCheck={onCheck}
          checkedKeys={state.checkedKeys}
          onSelect={onSelect}
          selectedKeys={state.selectedKeys}
        >
          {renderTreeNodes(treeData)}
        </Tree>
        <button onClick={createTree}>Validate</button>
        {state.newTreeView && (
          <Tree>{renderTreeNodes(state.newTreeData)}</Tree>
        )}
      </>
    );
  }

ReactDOM.render(<Demo />, document.getElementById("container"));