React删除未使用的sortType状态后状态不更新问题及解决
React操作State删除未使用变量后状态停止更新问题
问题描述
在实现自行车数据按年份排序功能时,删除代码中全程未使用的sortType状态相关代码后,出现状态停止更新、无任何报错、UI不刷新的异常;保留sortType相关代码时功能可正常运行。
问题代码
import BikeCard from "../components/BikeCard"; import Layout from "../components/Layout"; import { getAllBikes } from "../lib/bikes"; import Head from "next/head"; import { useState } from "react"; import BikeGallery from "../components/BikeGallery"; export default function Home({ data }) { const allBikes = []; // 默认数据 data.forEach((model) => model.bikes.forEach((bike) => allBikes.push(bike))); const [displayData, setDisplayData] = useState(allBikes); const [sortType, setSortType] = useState("make"); // 打算删除该行 const SortByInputHandler = (e) => { setSortType(e.target.value); // 打算删除该行 if (e.target.value === "year") { setDisplayData(sortByYear(allBikes)); // 按年份排序默认数据后存入State } else if (e.target.value === "make") { setDisplayData(allBikes); } }; const sortByYear = (data) => { let arr = data; arr.sort((a, b) => { return b.year > a.year ? 1 : b.year < a.year ? -1 : 0; }); return arr; }; return ( <Layout> <Head> <title>Ride 4 - Bikes</title> </Head> <div> <div> <label>排序方式:</label> <select onChange={SortByInputHandler}> <option value="make">品牌</option> <option value="year">年份</option> </select> </div> </div> <BikeGallery displayData={displayData} /> </Layout> ); } export async function getStaticProps() { const data = getAllBikes(); return { props: { data }, }; }
根因分析
- JavaScript中
Array.sort()是原地排序方法,原代码中let arr = data仅赋值了数组的引用,排序操作会直接修改原始的allBikes数组本身,没有生成新的数组。 - React更新State时会做浅比较,传入
setDisplayData的还是原来的数组引用时,React会判定State没有变化,不会触发组件重渲染。 - 保留
sortType相关代码时功能正常的原因:每次触发排序事件都会调用setSortType更新另一个State,只要有任意State更新就会触发组件重渲染,此时displayData虽然引用未变,但指向的原数组已经被原地修改,重渲染时会读取到最新值,所以看起来功能正常。删除sortType后没有其他State触发重渲染,displayData引用未被React识别为变化,就出现了状态不更新的表象。
解决方案
修改排序逻辑,创建原数组的副本再执行排序操作,保证返回的是全新的数组引用:
将sortByYear函数中的let arr = data修改为let arr = [...data],通过扩展运算符创建数组副本。
修复后完整代码
import BikeCard from "../components/BikeCard"; import Layout from "../components/Layout"; import { getAllBikes } from "../lib/bikes"; import Head from "next/head"; import { useState } from "react"; import BikeGallery from "../components/BikeGallery"; export default function Home({ data }) { const allBikes = []; data.forEach((model) => model.bikes.forEach((bike) => allBikes.push(bike))); const [displayData, setDisplayData] = useState(allBikes); const SortByInputHandler = (e) => { if (e.target.value === "year") { setDisplayData(sortByYear(allBikes)); } else if (e.target.value === "make") { setDisplayData(allBikes); } }; const sortByYear = (data) => { let arr = [...data]; arr.sort((a, b) => { return b.year > a.year ? 1 : b.year < a.year ? -1 : 0; }); return arr; }; return ( <Layout> <Head> <title>Ride 4 - Bikes</title> </Head> <div> <div> <label>排序方式:</label> <select onChange={SortByInputHandler}> <option value="make">品牌</option> <option value="year">年份</option> </select> </div> </div> <BikeGallery displayData={displayData} /> </Layout> ); } export async function getStaticProps() { const data = getAllBikes(); return { props: { data }, }; }
内容的提问来源于stack exchange,提问作者Dantcho
相关产品推荐
相关产品推荐

