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

React蛋糕列表搜索过滤表单失效报错问题修复

React 蛋糕搜索表单报错修复

问题根因

共5处代码错误,直接导致搜索失效、运行报错:

  • 自定义Hook调用语法错误:useGlobalContext 是封装的函数,在SearchForm和CakeList组件中调用时都没有加()执行,直接从函数对象上解构状态,拿到的所有值都是undefined,是触发运行时报错的核心原因
  • 状态命名不匹配:Context中存储过滤结果的状态名是filteredData,CakeList组件中错误写成了filteredResults,无法读取到正确的过滤后列表
  • 搜索词状态未更新:输入框触发onChange时传入了输入值,但searchCakes函数没有接收参数,也没有调用setSearchTerm同步更新搜索词状态,导致searchTerm始终为空字符串
  • 过滤列表无初始值:接口拉取到全量蛋糕数据后,没有给filteredData赋初始值,首次加载时过滤列表为空
  • 表单默认行为未拦截:搜索form没有绑定提交事件,输入时按回车会触发页面默认刷新

修复后代码

context.js

import React, { useState, useContext, useEffect } from "react";

const url = "https://cakeaddicts-api.herokuapp.com/cakes";

const AppContext = React.createContext();

const AppProvider = ({ children }) => {
  const [loading, setLoading] = useState(false);
  const [searchTerm, setSearchTerm] = useState("");
  const [cakes, setCakes] = useState([]);
  const [filteredData, setFilteredData] = useState([]);

  const fetchCakes = async () => {
    setLoading(true);
    try {
      const response = await fetch(url);
      const cakes = await response.json();
      if (cakes) {
        const newCakes = cakes.map((cake) => {
          const {
            id,
            image,
            cake_name,
            category,
            type,
            ingredients,
            instructions,
          } = cake;
          return {
            id,
            image,
            cake_name,
            category,
            type,
            ingredients,
            instructions,
          };
        });
        setCakes(newCakes);
        // 初始化过滤列表为全量蛋糕数据
        setFilteredData(newCakes);
      } else {
        setCakes([]);
        setFilteredData([]);
      }
      setLoading(false);
    } catch (error) {
      console.log(error);
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchCakes();
  }, []);

  return (
    <AppContext.Provider
      value={{
        loading,
        cakes,
        setSearchTerm,
        searchTerm,
        filteredData,
        setFilteredData,
      }}
    >
      {children}
    </AppContext.Provider>
  );
};

export const useGlobalContext = () => {
  return useContext(AppContext);
};

export { AppContext, AppProvider };

SearchForm.js

import React from "react";
import { useGlobalContext } from "../context";

const SearchForm = () => {
  // 修复:Hook调用加括号执行
  const { cakes, setSearchTerm, setFilteredData } = useGlobalContext();

  // 修复:接收输入值参数
  const searchCakes = (value) => {
    // 同步更新搜索词状态
    setSearchTerm(value);
    const keyword = value.toLowerCase().trim();
    if (keyword) {
      const filtered = cakes.filter((item) => {
        // 仅按蛋糕名搜索,需要全字段匹配可替换为原Object.values逻辑
        return item.cake_name.toLowerCase().includes(keyword);
      });
      setFilteredData(filtered);
    } else {
      setFilteredData(cakes);
    }
  };

  return (
    <section className="section search">
      {/* 修复:阻止表单默认提交刷新行为 */}
      <form className="search-form" onSubmit={(e) => e.preventDefault()}>
        <div className="form-control">
          <label htmlFor="name">Search Your Favourite Cake</label>
          <input
            type="text"
            id="name"
            onChange={(e) => searchCakes(e.target.value)}
          />
        </div>
      </form>
    </section>
  );
};

export default SearchForm;

注:原文件中未使用的CakeList导入已删除

CakeList.js

import React from "react";
import Cake from "./Cake";
import Loading from "./Loading";
import { useGlobalContext } from "../context.js";

const CakeList = () => {
  // 修复:Hook调用加括号,修正过滤列表状态名
  const { cakes, loading, searchTerm, filteredData } = useGlobalContext();

  if (loading) {
    return <Loading />;
  }

  return (
    <section className="section">
      <h2 className="section-title">Cakes</h2>
      <div className="cakes-center">
        {searchTerm.length > 0
          ? filteredData.map((cake) => {
              return <Cake key={cake.id} {...cake} />;
            })
          : cakes.map((item) => {
              return <Cake key={item.id} {...item} />;
            })}
      </div>
    </section>
  );
};

export default CakeList;

注:搜索触发阈值从原长度>1调整为>0,输入单个字符即可触发过滤,可根据业务需求自行调整


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:24:15