首页 > 解决方案 > React Hook 中的条件语句问题

问题描述

我编写了一个程序,该程序从电影中获取具有对象的数据,并将手表的状态添加到每个对象并将其置于状态中。整个程序正常运行我唯一的问题是,当我单击观看按钮时,我希望将按钮的文本更改为不观看并包含在观看列表中。在顶部,我有两个按钮,已观看和未观看,我单击了其中一个。显示我更改的电影列表,它们的状态 事实上,每次单击按钮时,我都希望该电影对象中的 Watched 状态更改为 false,然后再次单击为 true。我在代码中指定了注释我知道我的问题有点令人困惑,但感谢您帮助我

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

    const App = () => {
      const [getMovies, setMovie] = useState([]);
      const [getLoading, setLoading] = useState(true);
      const [getKeyword, setKeyword] = useState("");
      const [getOverSeven, setOverSeven] = useState(false);
      const [getWatched, setWatched] = useState(true);
      const [getNotWatched, setNotWatched] = useState(false);
      const [getTextBtn, setTextBtn] = useState(false);

      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);
          });
      }, []);
//This is the part that I want every time I click on the button of each movie
// to change the button to not watched and in the state of watching state
// to false and with the next click to become true
      function handleWatchedBtn(id) {
        setTextBtn(!getTextBtn);
        const index = getMovies.findIndex((p) => p.id === id);
        if (index) {
          if (getTextBtn === true) {
            setMovie({
              id,
              name,
              rate,
              watched: true,
            });
          } else {
            setMovie({
              id,
              name,
              rate,
              watched: false,
            });
          }
        }
      }
      function handleKeywordChange(e) {
        setKeyword(e.target.value);
      }
      function handleOverSevenChange(e) {
        setOverSeven(e.target.checked);
      }
      function handleShow() {
        setNotWatched(!getNotWatched);
        setWatched(!getWatched);
      }
      function filterItems(getKeyword, getOverSeven, getWatched, getNotWatched) {
        const arr = getMovies.map((item) => ({
          id: item.id,
          text: item.name,
          rate: item.rate,
          watched: item.watched,
        }));
        return arr
          .filter((item) =>
            item.text.toLowerCase().includes(getKeyword.toLowerCase())
          )
          .filter((item) => (getOverSeven ? item.rate > 7 : true))
          .filter((item) => (getWatched ? item.watched === true : getNotWatched))
          .filter((item) => (getNotWatched ? item.watched === false : getWatched));
      }
      const result = filterItems(
        getKeyword,
        getOverSeven,
        getNotWatched,
        getWatched
      );
      if (getLoading) {
        return "Please wait...";
      }
      return (
        <div>
          <div>
            <div>
              Keyword
              <input
                type="text"
                value={getKeyword}
                onChange={handleKeywordChange}
              />
            </div>
            <div>
              <button onClick={handleShow}>watch</button>
              <button onClick={handleShow}>not watch</button>
            </div>
            <div>
              Only over 7.0
              <input
                type="checkbox"
                checked={getOverSeven}
                onChange={handleOverSevenChange}
              />
            </div>
            <div>
              <ul>
                {result.map((item) => (
                  <li data-id={item.id}>
                    {`${item.id} : ${item.text} ${item.rate}`}{" "}
                    <button onClick={handleWatchedBtn}>
                      {getTextBtn ? "Not watched" : " Watched"}
                    </button>
                  </li>
                ))}
              </ul>
            </div>
          </div>
        </div>
      );
    };
    export default App;

标签: javascriptreactjs

解决方案


你的状态有太多的useState状态对象。最好将它们全部移动到一个状态。

接下来的问题watchednot watched按钮不起作用是你没有传递你movie idhandleShow功能。

也没有必要使用两个不同的布尔值getWatchedgetNotWached过滤电影列表,这会增加额外的复杂性。因此将其移动到单个变量中,例如filterByWatchwhich can be "ALL" | "WATCHED" | "NOT_WATCHED"。因此,您只需在切换时更改一个变量 -> 更少的状态更新

handleWatchedBtn功能也需要一些改变。您提取了单击以切换的电影的索引,但稍后在函数中没有使用它。

这是解决所有上述问题的尝试。

如果您对以下代码有任何疑问,请随时发表评论。

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

    const initialState = {
      movies: [],
      loading: true,
      searchKeyword: "",
      filterOverSeven: false,
      filterByWatch: "ALL" // Can be "ALL" | "WATCHED" | "NOT_WATCHED"
    };

    const App = () => {
      const [state, setState] = useState(initialState);

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

      function handleWatchedBtn(id) {
        setState((s) => ({
          ...s,
          movies: s.movies.map((movie) => {
            if (movie.id === id) {
              return { ...movie, watched: !movie.watched };
            }
            return movie;
          })
        }));
      }

      function handleKeywordChange(e) {
        setState((s) => ({ ...s, searchKeyword: e.target.value }));
      }

      function handleOverSevenChange(e) {
        setState((s) => ({ ...s, filterOverSeven: !s.filterOverSeven }));
      }

      function handleWatchedChange(filter) {
        setState((s) => ({ ...s, filterByWatch: filter }));
      }

      function filterItems() {
        return state.movies
          .filter((item) =>
            item.name.toLowerCase().includes(state.searchKeyword.toLowerCase())
          )
          .filter((item) => (state.filterOverSeven ? item.rate > 7 : true))
          .filter((item) =>
            state.filterByWatch === "ALL"
              ? true
              : item.watched === (state.filterByWatch === "WATCHED")
          );
      }

      if (state.loading) {
        return "Please wait...";
      }

      return (
        <div>
          <div>
            <div>
              Keyword
              <input
                type="text"
                value={state.searchKeyword}
                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={state.filterOverSeven}
                onChange={handleOverSevenChange}
              />
            </div>
            <div>
              <ul>
                {filterItems().map((movie) => (
                  <li data-id={movie.id}>
                    {`${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;


推荐阅读