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

在导航条组件中,我们可以添加以下代码。注意,我们正在使用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组件中。

要做到这一点,我们需要重构所有的子组件,将它们的状态移到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教程,看看我们是如何做到这一点的。