Skip to content
本页目录

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" }
]

alt

步骤一:将 UI 拆解为组件层级结构

alt

  • FilterableProductTable
    • SearchBar
    • ProductTable
      • ProductCategoryRow
      • ProductRow alt

步骤二:使用 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,因为可以通过被原始列表中的产品,根据搜索框文本和复选框的值进行计算。

步骤四:验证 state 应该被放置在哪里

alt

步骤五:添加反向数据流