javascript - 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;
解决方案
你的状态有太多的useState
状态对象。最好将它们全部移动到一个状态。
接下来的问题watched
和not watched
按钮不起作用是你没有传递你movie id
的handleShow
功能。
也没有必要使用两个不同的布尔值getWatched
来getNotWached
过滤电影列表,这会增加额外的复杂性。因此将其移动到单个变量中,例如filterByWatch
which 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;
推荐阅读
- css-selectors - hasClass 方法不返回布尔结果
- python - 如何找到列相对于另一列的非重复出现
- javascript - 如何在游戏银行中奖励数组玩家的数量 - 玩家(nodejs-javascript)
- css - 如何根据页面在页脚附近显示不同的文本
- sqlite - SQLite:使用索引是否应该导致大约 100% 的 CPU?
- mongodb - 更改 Mongo-express 的 8081 端口
- r - 函数参数中的 unordered_map
- javascript - 在字典数组中计算相同的值,当它添加到表中时
- postgresql - 在什么情况下会出现错误 23001 (restrict_violation)?
- javascript - 如何创建一个包含不重复而不是随机数的数组?