如何像应用程序一样在 React 中切换组件

How to Switch component in React like an app

我是 React 的初学者,我想制作一个带有仪表板的网络应用程序,如 Windows 磁贴。 我很容易生成它们。但我希望当我点击其中一个时,隐藏 Dash 菜单并显示子应用程序“Prog1”。当然,扭转它。当我单击关闭按钮时,它会关闭子应用程序并 returns 到 Dash 菜单(暗示它隐藏 Prog1 以显示 Dash)。

我可以用这样的函数隐藏 Dash 菜单:

fctHide = () => {
    this.setState({ isActive: false });
}

但是我怎样才能显示另一个可能具有 fctShow 之类功能的子应用程序?

我们是被迫将函数放在 class 中还是只是制作一个通用的 display/hide 函数? 有没有更简单和更新的方法来做到这一点(例如使用钩子)。

我的应用在 Codepen 上:codepen 我可以按需在这里给你看。

我很惊讶地看到很多问题或教程显示和隐藏按钮中的元素而不是在 class/HTML/template 等之间切换(我猜像 React Native 路由器)。

谢谢!

除非您要将旧应用程序转换为 React,即不是从头开始编写纯 React 应用程序,否则不要多次使用 ReactDOM.render。由于您想在组件之间共享活动状态,因此它应该存在于它们的 closest common ancestor.

我不确定您的仪表板应该如何工作,但这里有一个 demo. Here, APP is such closest ancestor. You don't need react-router if you are not using URL routes or the History API

import React from "react";
import "./styles.css";

class Dash extends React.Component {
  render() {
    const { isActive, fctHide, fctShow } = this.props;
    const elements = ["1", "2", "3", "4"];

    const items = [];

    for (const [index, value] of elements.entries()) {
      items.push(
        <button
          key={index}
          onClick={() => {
            fctShow(index);
          }}
        >
          {value}
        </button>
      );
    }

    // if (isActive) {
    return (
      <div>
        <table>
          <tbody>
            <tr>
              <td> {items} </td>
            </tr>
          </tbody>
        </table>
      </div>
    );
    // } else {
    //   return null;
    // }
  }
}

class Prog1 extends React.Component {
  render() {
    const { isActive, selected, fctHide } = this.props;

    if (isActive) {
      return (
        <div className="contProg1">
          <button onClick={fctHide}>Close</button>
          <h1>Program 1</h1>
          <h2>Test1</h2>
          <h2>Test2</h2>
          <h2>Test3</h2>
          Selected: {selected}
          <ul>
            <li>AAAAA</li>
            <li>BBBBB</li>
            <li>CCCCC</li>
          </ul>
        </div>
      );
    } else {
      return null;
    }
  }
}

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isActive: true, selected: null };
  }

  fctShow = selected => {
    this.setState({ isActive: true, selected });
  };

  fctHide = () => {
    this.setState({ isActive: false });
  };

  render() {
    const { isActive, selected } = this.state;

    return (
      <>
        <Dash
          isActive={isActive}
          fctHide={this.fctHide}
          fctShow={this.fctShow}
        />
        <Prog1 isActive={isActive} selected={selected} fctHide={this.fctHide} />
      </>
    );
  }
}

好的!我最终使用了建议的 react-router。但是我使用了 Hooks 版本(带有 ...)

因此,小仪表板分为 X 个部分:

  • HTML只有最小值和根。 <div id="root"></div>
  • CSS(无话可说)
  • 特定文件夹“Apps”中的子应用程序
import React from "react";
import { A } from "hookrouter";

class Prog1 extends React.Component {
  render() {
    return (
      <div class="contProg1">
        <button class="close">
          {" "}
          <A href="/">Close</A>
        </button>
        <h1>Program 1</h1>
        <h2>Test1</h2>
        <h2>Test2</h2>
        <h2>Test3</h2>
        <ul>
          <li>AAAAA</li>
          <li>BBBBB</li>
          <li>CCCCC</li>
        </ul>
      </div>
    );
  }
}

export default Prog1;
  • 在应用程序和主 Dash 之间切换的路由器页面。
import React from "react";
import Prog1 from "./Apps/Prog1";
import Prog2 from "./Apps/Prog2";
import Prog3 from "./Apps/Prog3";
import Prog4 from "./Apps/Prog4";
import Dash from "./App";

const routes = {
  "/": () => <Dash />,
  "/Prog1": () => <Prog1 />,
  "/Prog2": () => <Prog2 />,
  "/Prog3": () => <Prog3 />,
  "/Prog4": () => <Prog4 />
};

export default routes;

  • 主页,仪表板 (App.js)。
import React from "react";
import { A } from "hookrouter";

const elements = ["1", "2", "3", "4"];

function Dash() {
  const items = [];

  for (const [index, value] of elements.entries()) {
    items.push(
      <A href={"/Prog" + (index + 1)}>
        <button key={index}>{value}</button>
      </A>
    );
  }

  return (
    <div className="Dash">
      <table>
        <tr>
          <td> {items} </td>
        </tr>
      </table>
    </div>
  );
}

export default Dash;
  • 最后,索引页:
import React from "react";
import { render } from "react-dom";
import "./styles.css";
import { useRoutes } from "hookrouter";
import routes from "./router";
import NoPageFound from "./Apps/404";

function App() {
  const routeResult = useRoutes(routes);
  return <div className="Dash">{routeResult || <NoPageFound />}</div>;
}

render(<App />, document.getElementById("root"));

效果很好。我只需要添加 MemoryRouter 之类的东西来隐藏 URL 并为移动版本做准备。 当我将这部分插入 Django 项目时,我有点害怕。 或者,也许我应该把它分开? (你不用回答,我想我就关了)。

谢谢:)