You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中未使用Hook时,依赖状态的变量为何随状态变化?

React状态更新时,非Hook计算变量随状态变化的原因

我是React.js新手,学习官网示例代码时对运行机制产生困惑。修改代码新增变量temp后,发现它会随状态filterText的变化而改变。我推测这是因为temp直接由filterText计算而来,但想了解根本原因。尝试了多个由状态计算、未放入任何Hook的变量,它们均会随状态变化,却未在网上找到相关解释,恳请解答。

import { useState } from 'react';

function FilterableProductTable({ products }) {
  const [filterText, setFilterText] = useState('');
  const [inStockOnly, setInStockOnly] = useState(false);
  const temp = filterText[0];

  return (
    <div>
      <SearchBar
        filterText={filterText}
        inStockOnly={inStockOnly}
        onFilterTextChange={setFilterText}
        onInStockOnlyChange={setInStockOnly} />
      <ProductTable
        products={products}
        filterText={filterText}
        inStockOnly={inStockOnly} />
      {temp}
    </div>
  );
}

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>
  );
}

function ProductTable({ products, filterText, inStockOnly }) {
  const rows = [];
  let lastCategory = null;

  products.forEach((product) => {
    if (
      product.name.toLowerCase().indexOf(
        filterText.toLowerCase()
      ) === -1
    ) {
      return;
    }
    if (inStockOnly && !product.stocked) {
      return;
    }
    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>Name</th>
          <th>Price</th>
        </tr>
      </thead>
      <tbody>{rows}</tbody>
    </table>
  );
}

function SearchBar({
  filterText,
  inStockOnly,
  onFilterTextChange,
  onInStockOnlyChange
}) {
  return (
    <form>
      <input
        type="text"
        value={filterText} placeholder="Search..."
        onChange={(e) => onFilterTextChange(e.target.value)} />
      <label>
        <input
          type="checkbox"
          checked={inStockOnly}
          onChange={(e) => onInStockOnlyChange(e.target.checked)} />
        {' '}
        Only show products in stock
      </label>
    </form>
  );
}

const PRODUCTS = [
  {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"}
];

export default function App() {
  return <FilterableProductTable products={PRODUCTS} />;
}

解答

这本质是React的组件重渲染机制导致的:

  • 当调用setFilterText修改filterText状态时,React会标记FilterableProductTable组件需要重新渲染。
  • 组件重新渲染时,整个FilterableProductTable函数会被重新执行一遍。
  • 每次函数执行时,const temp = filterText[0];这行代码都会重新运行,用当前最新的filterText值计算出temp的新值,所以你会看到temp随filterText变化。

所有直接依赖状态/ props的普通变量,都会在组件重渲染时重新计算,这是React函数组件的正常行为——因为函数组件本身就是一个渲染函数,每次重渲染都会从头执行,生成新的变量值。

如果某些计算逻辑比较复杂,不想每次重渲染都重复计算,可以用useMemo Hook来缓存计算结果,但对于简单的取值(比如取字符串第一个字符),完全没必要,直接写普通变量就好。

内容的提问来源于stack exchange,提问作者陈皮皮

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 04:23:13