在从父组件到子组件创建项目时,在 React 中进入无限循环
While creating item from parent to child component, going to infinite loop in React
这是我的主页,获取列表数据然后根据需要创建列表组件。
然后转到列表组件并创建列表项。所以使用 map 函数创建新组件。我尝试了不同的方法,但我无法弄清楚。无论我做什么,它都会无限循环。
Home.jsx
const [lists, setLists] = useState([]);
useEffect(() => {
const getRandomList = async () => {
try {
const res = await axios.get(`/lists${type ? "?type=" + type : ""}`, {
headers: {
"Content-Type": "application/json;charset=UTF-8",
token: token,
},
});
setLists(res.data);
} catch (error) {
console.log(error);
}
};
getRandomList();
}, [type]);
return (
<div className="home">
<Navbar />
<Featured type={type} />
{lists.map((list, index) => {
return <List key={index} list={list}/>;
})}
</div>
);
}
在List组件中,根据需要创建List item组件。
List.jsx
export default function List({ list }) {
const [isMoved, setIsMoved] = useState(false);
const [slideNumber, setSlideNumber] = useState(0);
const [clickLimit, setClickLimit] = useState(window.innerWidth / 230);
const [lists, setLists] = useState([])
const listRef = useRef();
useEffect( () =>{
const getList = ()=>{
setLists(list.content)
}
getList()
},[list])
const handleClick = (direction) => {
setIsMoved(true);
let distance = listRef.current.getBoundingClientRect().x - 50;
if (direction === "left" && slideNumber > 0) {
setSlideNumber(slideNumber - 1);
listRef.current.style.transform = `translateX(${230 + distance}px)`;
}
if (direction === "right" && slideNumber < 10 - clickLimit) {
setSlideNumber(slideNumber + 1);
listRef.current.style.transform = `translateX(${-230 + distance}px)`;
}
};
return (
<div className="list">
<span className="listTitle">Continue to watch</span>
<div className="listWrapper">
<ArrowBackIosOutlined
className="sliderArrow left"
onClick={() => handleClick("left")}
style={{ display: !isMoved && "none" }}
/>
<div className="listContainer" ref={listRef}>
{lists.map((item, index) => {
return <ListItem key={index} index={index} item={item} />;
})}
</div>
<ArrowForwardIosOutlined
className="sliderArrow right"
onClick={() => handleClick("right")}
/>
</div>
</div>
);
}
这里是最后一个组成部分。
ListItem.jsx
export default function ListItem({ index, item }) {
const [isHovered, setIsHovered] = useState(false);
const [movie, setMovie] = useState({});
useEffect(() => {
const getMovie = async (item) => {
try {
const res = await axios.get("/movies/find/" + item, {
headers: {
"Content-Type": "application/json;charset=UTF-8",
token: token,
},
});
setMovie(res.data);
} catch (error) {
console.log(error);
}
};
getMovie()
}, [item]);
return (
<div
className="listItem"
style={{
left:
isHovered &&
Object.values(index) * 225 - 50 + Object.values(index) * 2.5,
}}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<img src={movie.img} alt="" />
{isHovered && (
<>
<video src={movie.trailer} autoPlay loop></video>
<div className="itemInfo">
<div className="itemIcons">
<PlayArrow className="itemIcon" />
<Add className="itemIcon" />
<ThumbUpAltOutlined className="itemIcon" />
<ThumbDownAltOutlined className="itemIcon" />
</div>
<div className="itemInfoTop">
<span>1 hour 14 mins</span>
<span className="limit">{movie.limit}</span>
<span>{movie.year}</span>
</div>
<div className="itemDescription">{movie.description}</div>
<div className="itemGenre">{movie.genre}</div>
</div>
</>
)}
</div>
);
}
尝试从 List
组件中删除 useEffect
并直接从 list.content
中删除 map
:
export default function List({ list }) {
const [isMoved, setIsMoved] = useState(false);
const [slideNumber, setSlideNumber] = useState(0);
const [clickLimit, setClickLimit] = useState(window.innerWidth / 230);
const listRef = useRef();
const handleClick = (direction) => {
setIsMoved(true);
let distance = listRef.current.getBoundingClientRect().x - 50;
if (direction === "left" && slideNumber > 0) {
setSlideNumber(slideNumber - 1);
listRef.current.style.transform = `translateX(${230 + distance}px)`;
}
if (direction === "right" && slideNumber < 10 - clickLimit) {
setSlideNumber(slideNumber + 1);
listRef.current.style.transform = `translateX(${-230 + distance}px)`;
}
};
return (
<div className="list">
<span className="listTitle">Continue to watch</span>
<div className="listWrapper">
<ArrowBackIosOutlined
className="sliderArrow left"
onClick={() => handleClick("left")}
style={{ display: !isMoved && "none" }}
/>
<div className="listContainer" ref={listRef}>
{list.content.map((item, index) => {
return <ListItem key={index} index={index} item={item} />;
})}
</div>
<ArrowForwardIosOutlined
className="sliderArrow right"
onClick={() => handleClick("right")}
/>
</div>
</div>
);
}
这是我的主页,获取列表数据然后根据需要创建列表组件。 然后转到列表组件并创建列表项。所以使用 map 函数创建新组件。我尝试了不同的方法,但我无法弄清楚。无论我做什么,它都会无限循环。
Home.jsx
const [lists, setLists] = useState([]);
useEffect(() => {
const getRandomList = async () => {
try {
const res = await axios.get(`/lists${type ? "?type=" + type : ""}`, {
headers: {
"Content-Type": "application/json;charset=UTF-8",
token: token,
},
});
setLists(res.data);
} catch (error) {
console.log(error);
}
};
getRandomList();
}, [type]);
return (
<div className="home">
<Navbar />
<Featured type={type} />
{lists.map((list, index) => {
return <List key={index} list={list}/>;
})}
</div>
);
}
在List组件中,根据需要创建List item组件。
List.jsx
export default function List({ list }) {
const [isMoved, setIsMoved] = useState(false);
const [slideNumber, setSlideNumber] = useState(0);
const [clickLimit, setClickLimit] = useState(window.innerWidth / 230);
const [lists, setLists] = useState([])
const listRef = useRef();
useEffect( () =>{
const getList = ()=>{
setLists(list.content)
}
getList()
},[list])
const handleClick = (direction) => {
setIsMoved(true);
let distance = listRef.current.getBoundingClientRect().x - 50;
if (direction === "left" && slideNumber > 0) {
setSlideNumber(slideNumber - 1);
listRef.current.style.transform = `translateX(${230 + distance}px)`;
}
if (direction === "right" && slideNumber < 10 - clickLimit) {
setSlideNumber(slideNumber + 1);
listRef.current.style.transform = `translateX(${-230 + distance}px)`;
}
};
return (
<div className="list">
<span className="listTitle">Continue to watch</span>
<div className="listWrapper">
<ArrowBackIosOutlined
className="sliderArrow left"
onClick={() => handleClick("left")}
style={{ display: !isMoved && "none" }}
/>
<div className="listContainer" ref={listRef}>
{lists.map((item, index) => {
return <ListItem key={index} index={index} item={item} />;
})}
</div>
<ArrowForwardIosOutlined
className="sliderArrow right"
onClick={() => handleClick("right")}
/>
</div>
</div>
);
}
这里是最后一个组成部分。
ListItem.jsx
export default function ListItem({ index, item }) {
const [isHovered, setIsHovered] = useState(false);
const [movie, setMovie] = useState({});
useEffect(() => {
const getMovie = async (item) => {
try {
const res = await axios.get("/movies/find/" + item, {
headers: {
"Content-Type": "application/json;charset=UTF-8",
token: token,
},
});
setMovie(res.data);
} catch (error) {
console.log(error);
}
};
getMovie()
}, [item]);
return (
<div
className="listItem"
style={{
left:
isHovered &&
Object.values(index) * 225 - 50 + Object.values(index) * 2.5,
}}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<img src={movie.img} alt="" />
{isHovered && (
<>
<video src={movie.trailer} autoPlay loop></video>
<div className="itemInfo">
<div className="itemIcons">
<PlayArrow className="itemIcon" />
<Add className="itemIcon" />
<ThumbUpAltOutlined className="itemIcon" />
<ThumbDownAltOutlined className="itemIcon" />
</div>
<div className="itemInfoTop">
<span>1 hour 14 mins</span>
<span className="limit">{movie.limit}</span>
<span>{movie.year}</span>
</div>
<div className="itemDescription">{movie.description}</div>
<div className="itemGenre">{movie.genre}</div>
</div>
</>
)}
</div>
);
}
尝试从 List
组件中删除 useEffect
并直接从 list.content
中删除 map
:
export default function List({ list }) {
const [isMoved, setIsMoved] = useState(false);
const [slideNumber, setSlideNumber] = useState(0);
const [clickLimit, setClickLimit] = useState(window.innerWidth / 230);
const listRef = useRef();
const handleClick = (direction) => {
setIsMoved(true);
let distance = listRef.current.getBoundingClientRect().x - 50;
if (direction === "left" && slideNumber > 0) {
setSlideNumber(slideNumber - 1);
listRef.current.style.transform = `translateX(${230 + distance}px)`;
}
if (direction === "right" && slideNumber < 10 - clickLimit) {
setSlideNumber(slideNumber + 1);
listRef.current.style.transform = `translateX(${-230 + distance}px)`;
}
};
return (
<div className="list">
<span className="listTitle">Continue to watch</span>
<div className="listWrapper">
<ArrowBackIosOutlined
className="sliderArrow left"
onClick={() => handleClick("left")}
style={{ display: !isMoved && "none" }}
/>
<div className="listContainer" ref={listRef}>
{list.content.map((item, index) => {
return <ListItem key={index} index={index} item={item} />;
})}
</div>
<ArrowForwardIosOutlined
className="sliderArrow right"
onClick={() => handleClick("right")}
/>
</div>
</div>
);
}