如何在React中创建一个导航条组件

441 阅读3分钟

在本教程中,我们将向我们在React中构建的应用程序添加一个NavBar组件。在这个过程中,我们需要做一些重构,以便将本地状态从子组件中转移到App父组件中。通过遵循这一惯例,我们需要在子组件中引发事件,同时在父组件中处理这些事件。这允许我们的应用程序有一个单一的真相来源。换句话说,几个组件可以反映基于相同变化数据的更新。现在让我们看看这是如何工作的。


添加导航条组件文件

首先,我们可以在我们一直使用的组件文件夹中添加一个新的navbar.jsx文件。
react navbar file

在导航条组件中,我们可以添加以下代码。注意,我们正在使用props对象来获取应用程序中的项目总数,这样我们就可以在导航区显示它们。

import React, { Component } from "react";

class NavBar extends Component {
  render() {
    return (
      <React.Fragment>
        <nav className="navbar navbar-dark bg-dark mb-3">
          <a className="navbar-brand" href="#">
            <h1>Total Items <span className="badge badge-secondary">{this.props.totalItems}</span></h1>
          </a>
        </nav>
      </React.Fragment>
    );
  }
}

export default NavBar;

重新配置为使用App.js

我们想恢复到使用App.js作为应用程序的主要组件。要做到这一点,我们可以对index.js进行调整,以便我们现在呈现而不是,像这样。
index.js

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import "bootstrap/dist/css/bootstrap.css";

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

在React中解除状态

在React中工作时,你有时会听到关于提升状态的说法。React文档对这个概念描述如下。

通常情况下,几个组件需要反映相同的变化数据。我们建议将共享状态提升到它们最接近的共同祖先。让我们看看这在实际中是如何运作的。

在我们的案例中,这意味着我们要有以下的应用布局,其中状态现在驻留在顶层的App组件中。

react lift state

要做到这一点,我们需要重构所有的子组件,将它们的状态移到App组件中。这就是我们新的App组件。顶部是共享状态,然后是事件处理程序,最后是render()方法。如果你需要复习一下这些概念,请看之前的React教程。为了在递增时将总的项目加起来,我们使用了JavaScript reduce()方法
App.js

import React, { Component } from "react";
import NavBar from "./components/navbar";
import Items from "./components/items";
import "./App.css";

class App extends Component {
  state = {
    items: [{ id: 1, value: 0 }, { id: 2, value: 0 }, { id: 3, value: 0 }]
  };

  handleIncrement = item => {
    const items = [...this.state.items];
    const index = items.indexOf(item);
    items[index] = { ...item };
    items[index].value++;
    this.setState({ items });
  };

  handleReset = () => {
    const items = this.state.items.map(i => {
      i.value = 0;
      return i;
    });
    this.setState({ items });
  };

  handleDelete = itemId => {
    const items = this.state.items.filter(item => item.id !== itemId);
    this.setState({ items: items });
  };

  render() {
    return (
      <React.Fragment>
        <NavBar
          totalItems={this.state.items.reduce((prev, cur) => {
            return prev + cur.value;
          }, 0)}
        />
        <Items
          onReset={this.handleReset}
          onDelete={this.handleDelete}
          onIncrement={this.handleIncrement}
          items={this.state.items}
        />
      </React.Fragment>
    );
  }
}

export default App;

重构的儿童组件

由于所有的状态和逻辑都被提升到顶级的App组件,我们的和组件现在更加精简。事实上,它们甚至不再有任何本地状态。如果它们需要处理数据,它们必须通过props对象获得。此外,为了更新数据,事件在子对象中被引发,在父对象中被处理

items.jsx

import React, { Component } from "react";
import Item from "./item";

class Items extends Component {
  render() {
    return (
      <React.Fragment>
        <button
          onClick={this.props.onReset}
          className="btn btn-success btn-lg m-3"
        >
          Reset All
        </button>
        {this.props.items.map(item => (
          <Item
            key={item.id}
            onDelete={this.props.onDelete}
            onIncrement={this.props.onIncrement}
            item={item}
          />
        ))}
      </React.Fragment>
    );
  }
}

export default Items;

item.jsx

import React, { Component } from "react";

class Item extends Component {
  render() {
    return (
      <React.Fragment>
        <div className="card mb-2">
          <h5 className={this.styleCardHeader()}>{this.styleCount()}</h5>
          <div className="card-body">
            <button
              onClick={() => this.props.onIncrement(this.props.item)}
              className="btn btn-lg btn-outline-secondary"
            >
              Increment
            </button>

            <button
              onClick={() => this.props.onDelete(this.props.item.id)}
              className="btn btn-lg btn-outline-danger ml-4"
            >
              Delete
            </button>
          </div>
        </div>
      </React.Fragment>
    );
  }

  styleCardHeader() {
    let classes = "card-header h4 text-white bg-";
    classes += this.props.item.value === 0 ? "warning" : "primary";
    return classes;
  }

  styleCount() {
    const { value } = this.props.item;
    return value === 0 ? "No Items!" : value;
  }
}

export default Item;

行动中的共享状态

现在,当我们与应用程序互动时,我们可以看到一些概念在发挥作用。在每个单独的项目上点击增量按钮,就会增加该项目的数量。此外,NavBar组件现在正在跟踪所有项目值的总和。最后,我们可以点击一个按钮,将所有的计数器重置为零。


在React中创建一个导航条组件 摘要

在本教程中,我们做了一些很好的重构工作,为应用程序添加了一个导航条组件。我们学习了一些关于在react中提升状态的知识,以及如何提升和处理事件。如果你还没有,请查看之前的React教程,看看我们是如何做到这一点的。