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

React Hooks点击切换按钮状态及按观影状态筛选列表问题求解

你的代码存在两处语法错误,修正后即可实现需求:


错误1:handleWatchedBtn 状态更新逻辑错误

你在修改对应id的电影对象时,没有展开原有属性,导致新生成的对象多了一层movie嵌套,watched字段没有直接挂载到电影对象上,状态切换无法生效。同时setMovie回调没有接收最新状态参数,异步场景下可能读取旧值。
修正后的代码:

function handleWatchedBtn(id) {
  setMovie(prevMovies =>
    prevMovies.map((movie) => {
      if (movie.id === id) {
        // 展开原有对象,仅覆盖watched字段
        return { ...movie, watched: !movie.watched };
      }
      return movie;
    })
  );
}

错误2:handleWatchedChange 筛选状态赋值错误

filterByWatch状态设计为存储字符串类型的筛选标记,你错误传入了对象结构,导致后续筛选逻辑判断失效。
修正后的代码:

function handleWatchedChange(filter) {
  // 直接传入筛选标记字符串即可
  setfilterByWatch(filter);
}

完整修正代码

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

const App = () => {
  const [Movies, setMovie] = useState([]);
  const [Loading, setLoading] = useState(true);
  const [Keyword, setKeyword] = useState("");
  const [OverSeven, setOverSeven] = useState(false);
  const [filterByWatch, setfilterByWatch] = useState("ALL");

  useEffect(() => {
    fetch("http://my-json-server.typicode.com/bemaxima/fake-api/movies")
      .then((response) => response.json())
      .then((response) => {
        setMovie(
          response.map((item) => ({
            id: item.id,
            name: item.name,
            rate: item.rate,
            watched: false,
          }))
        );
        setLoading(false);
      });
  }, []);

  function handleWatchedBtn(id) {
    setMovie(prevMovies =>
      prevMovies.map((movie) => {
        if (movie.id === id) {
          return { ...movie, watched: !movie.watched };
        }
        return movie;
      })
    );
  }

  function handleWatchedChange(filter) {
    setfilterByWatch(filter);
  }

  function handleKeywordChange(e) {
    setKeyword(e.target.value);
  }
  function handleOverSevenChange(e) {
    setOverSeven(e.target.checked);
  }

  function filterItems() {
    return Movies.filter((item) =>
      item.name.toLowerCase().includes(Keyword.toLowerCase())
    )
      .filter((item) => (OverSeven ? item.rate > 7 : true))
      .filter((item) =>
        filterByWatch === "ALL"
          ? true
          : item.watched === (filterByWatch === "WATCHED")
      );
  }
  if (Loading) {
    return "Please wait...";
  }
  return (
    <div>
      <div>
        <div>
          Keyword
          <input type="text" value={Keyword} onChange={handleKeywordChange} />
        </div>
        <div>
          <button onClick={() => handleWatchedChange("ALL")}>all</button>
          <button onClick={() => handleWatchedChange("WATCHED")}>watch</button>
          <button onClick={() => handleWatchedChange("NOT_WATCHED")}>
            not watch
          </button>
        </div>
        <div>
          Only over 7.0
          <input
            type="checkbox"
            checked={OverSeven}
            onChange={handleOverSevenChange}
          />
        </div>
        <div>
          <ul>
            {filterItems().map((movie) => (
              <li data-id={movie.id} key={movie.id}>
                {`${movie.name} ${movie.rate}`}{" "}
                <button onClick={() => handleWatchedBtn(movie.id)}>
                  {movie.watched ? "Watched" : " Not watched"}
                </button>
              </li>
            ))}
          </ul>
        </div>
      </div>
    </div>
  );
};
export default App;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 05:09:02