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,提问作者陈皮皮
相关产品推荐
相关产品推荐

