React如何进行思考构建组件和应用程序
当你使用 React 构建用户界面时,你首先会把它分解成一个个 组件,然后,你需要把这些组件连接在一起,使数据流经它们。
JSON API 返回如下的数据:
json
[
{ category: "Fruits", price: "$1", stocked: true, name: "Apple" },
{ category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit" },
{ category: "Fruits", price: "$2", stocked: false, name: "Passionfruit" },
{ category: "Vegetables", price: "$2", stocked: true, name: "Spinach" },
{ category: "Vegetables", price: "$4", stocked: false, name: "Pumpkin" },
{ category: "Vegetables", price: "$1", stocked: true, name: "Peas" }
]
步骤一:将 UI 拆解为组件层级结构
- FilterableProductTable
- SearchBar
- ProductTable
- ProductCategoryRow
- ProductRow
步骤二:使用 React 构建一个静态版本
JSX
import React from "react"
//水果/蔬菜类别组件
function ProductCategoryRow ({ category }) {
return (
<tr>
<th colSpan="2">{category}</th>
</tr>
)
}
//价格判断组件
function ProductRow ({ product }) {
const name = product.stocked ? (product.name) : (
<span style={{ color: "red" }}>{product.name}</span>
)
return (
<tr>
<td>{name}</td>
<td>{product.price}</td>
</tr>
)
}
//table 组件
function ProductTable ({ products }) {
const rows = []
let lastCategory = null
products.forEach((product) => {
if (product.category !== lastCategory) {
rows.push(
<ProductCategoryRow
category={product.category}
key={product.category}
/>
)
}
rows.push(<ProductRow product={product} key={product.name} />)
lastCategory = product.category
})
return (
<table>
<thead>
<tr>
<th>名字</th>
<th>价格</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
)
}
function SearchBar () {
return (
<form>
<input type="text" placeholder="Search..." />
<label>
<input type="checkbox" /> 仅显示库存产品
</label>
</form>
)
}
function FilterableProductTable ({ products }) {
return (
<div>
<SearchBar />
<ProductTable products={products} />
</div>
)
}
const PRODUCTS = [
{ category: "水果", price: "$1", stocked: true, name: "苹果" },
{ category: "水果", price: "$1", stocked: true, name: "火龙果" },
{ category: "水果", price: "$2", stocked: false, name: "番茄" },
{ category: "蔬菜", price: "$2", stocked: true, name: "菠菜" },
{ category: "蔬菜", price: "$4", stocked: false, name: "南瓜" },
{ category: "蔬菜", price: "$1", stocked: true, name: "豌豆" }
]
export default function App () {
return <FilterableProductTable products={PRODUCTS} />
}
步骤三:找出 UI 精简且完整的 state 表示
现在考虑示例应用程序中的每一条数据:
- 1.原始列表中的产品 被作为 props 传递,所以不是 state。
- 2.搜索文本似乎应该是 state,因为它会随着时间的推移而变化,并且无法从任何东西中计算出来。
- 3.复选框的值似乎是 state,因为它会随着时间的推移而变化,并且无法从任何东西中计算出来。
- 4.过滤后列表中的产品 不是 state,因为可以通过被原始列表中的产品,根据搜索框文本和复选框的值进行计算。