React useState数组调用includes方法始终返回false问题排查
问题根源
Array.prototype.includes 底层使用**严格相等(===)**做匹配,始终返回false基本逃不出两个原因:
- 类型不匹配:本地用于校验的
id是数字类型,接口返回的id值是字符串类型,数字1和字符串"1"严格相等结果为false,自然永远匹配不上。Axios不会自动将字符串格式的数字转为Number类型,这是前端接口联调最常见的坑。 - 数组结构不匹配:如果接口返回的
response.data是带id字段的对象数组(比如结构为[{id: 1, slot: "09:00"}, ...]),而非纯id值组成的数组,直接调用includes(数字id)永远不可能匹配——数组元素是对象,和基础类型的数字不可能严格相等。
另外你的渲染逻辑里还有一个隐藏bug:id++写在了返回按钮的分支里,只要走到返回<h1>Testing</h1>的分支,id就不会自增,后续所有循环的id都会卡在同一个值,判断逻辑会完全混乱。
修复方案
- 统一数据结构和类型:拿到接口返回值后先做预处理,要么转成纯数字id的数组再存入状态,要么调整判断逻辑适配对象数组。
- 把id自增逻辑挪到分支判断外,保证每次循环不管渲染什么内容,id都能正常累加。
参考修复代码
接口请求部分预处理:
const [freeSlotsList, setFreeSlotsList] = useState([]); useEffect(() => { Axios.post("http://localhost:3001/api/get/week1/ex").then((response) => { // 方案1:提取所有id转成数字,生成纯id数组,适配你原来的includes写法 const idList = response.data.map(item => Number(item.id)); setFreeSlotsList(idList); // 如果你不想改原数组结构,也可以直接存原数据,后面判断改用some方法 // setFreeSlotsList(response.data); }); }, []);
渲染逻辑修复:
const renderTableData = () => { let id = 1; const activeButton = () => {}; return ( <tr> {days.map((val) => ( <td> {timeSlot.map((n, i) => { // 先取当前id,不管走哪个分支都完成自增,避免id卡住 const currentId = id++; // 如果你存的是纯id数组,用原来的includes即可 if (!freeSlotsList.includes(currentId)) { return <h1>Testing</h1>; } // 如果你存的是原对象数组,把上面的判断换成下面这行 // if (!freeSlotsList.some(slot => Number(slot.id) === currentId)) { // return <h1>Testing</h1>; // } return ( <button id={currentId} className={activeButton}> {n} {currentId} </button> ); })} </td> ))} </tr> ); };
排查小技巧:如果不确定类型和结构,直接在判断前打印
console.log(freeSlotsList, typeof freeSlotsList[0], typeof id),一眼就能定位问题。
内容的提问来源于stack exchange,提问作者Max Andersson
相关产品推荐
相关产品推荐

