问题描述
我编写了一个程序,它从电影中获取一个对象的数据,并将手表的状态添加到每个对象中,并将其放入该状态。 整个程序运行正常 我唯一的问题是,当我单击已观看按钮时,我希望将按钮的文本更改为未观看并包含在观看列表中。 在顶部,我有两个按钮,观看和未观看,我点击了其中一个。显示我更改的电影列表,它们的状态 实际上,每次点击按钮时,我都希望那部电影的对象中的 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,});
}
}
}
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,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,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
)中,它可以是 { {1}}。所以你只需要在切换时更改一个变量 -> 更少的状态更新
"ALL" | "WATCHED" | "NOT_WATCHED"
函数也需要一些改变。您提取了单击以进行切换的电影索引,但稍后未在函数中使用该索引。
尝试解决上述所有问题。
如果您对以下代码有任何疑问,请随时发表评论。
handleWatchedBtn