React Hooks useState useEffect 幻灯片
React Hooks useState useEffect slideshow
我正在尝试通过道具将以下数据传递给 Slide.js
来制作幻灯片应用程序。
const SLIDES = [
{
title: "Today's workout plan",
text: "We're gonna do 3 fundamental exercises."
},
{
title: "First, 10 push-ups",
text: "Do 10 reps. Remember about full range of motion. Don't rush."
},
{
title: "Next, 20 squats",
text: "Squats are important. Remember to keep your back straight."
},
{
title: "Finally, 15 sit-ups",
text: "Slightly bend your knees. Remember about full range of motion."
},
{
title: "Great job!",
text: "You made it, have a nice day and see you next time!"
}
];
我的子组件Slide.js
具有以下代码
import React, { useState, useEffect } from "react";
function Slides({ slides }) {
const [slideShow, setSlide] = useState(slides);
useEffect(() => {
setSlide(slideShow[0]);
console.log("slides", slideShow[0]);
}, []);
return (
<div>
<div id="navigation" className="text-center">
<button data-testid="button-restart" className="small outlined">
Restart
</button>
<button data-testid="button-prev" className="small">
Prev
</button>
<button data-testid="button-next" className="small">
Next
</button>
</div>
{slideShow.map((slide, i) => (
<div id={i} className="card text-center">
<h1 data-testid="title">{slide.title}</h1>
<p data-testid="text">{slide.text}</p>
</div>
))}
</div>
);
}
export default Slides;
我认为使用 setSlide(slideShow[0])
只会在应用程序初始加载后呈现对象数组中的第一项。但是我得到
TypeError: slideShow.map is not a function
但是当我console.log("slides", slideShow[0])
我输出
slides {title: "Today's workout plan", text: "We're gonna do 3 fundamental exercises."}
如果我将代码更改为
setSlide(slideShow.slice(0, 1));
该应用程序仅显示数组中的第一个对象,但如果我 console.log("slides", slideShow)
,即使我认为我应该收到切片版本,我也会得到整个对象数组。
我的 map
函数是否没有引用 slideShow[0]
导致错误发生?
useState 本质上是异步的,但不是 return 承诺,但要解决 useState 的异步性质和快速肮脏的修复方法就是对您的数据进行空传播,例如
幻灯片?.地图
但我会怎么做,就像这样:
只是给你一些想法
import SLIDES from ....slides.etc
const [slideIndex, setSlideIndex]=useState(0)
<item onClick={()=>{setSlideIndex(slideIndex + 1)}} >
{SLIDES[slideIndex]}
</item>
举个例子给大家参考
引用此行时出现错误slideShow.map((slide, i) => (
问题在于您的 useEffect 在您的组件呈现后被调用,并且您将幻灯片放映设置为单张幻灯片 slideShow[0]
。然后您继续 re-render 您的组件,并尝试映射到 slideShow,但幻灯片等于原始幻灯片变量 (slideshow[0]
) 的第一项并且您无法映射到单个幻灯片.
您可能希望将代码编辑得更像
function Slides({ slides }) {
const [slideIdx, setSlide] = useState(0);
const updateIndex = (val) => {
if (val === -1){
if (slideIdx === 0){
setSlide(slides.length -1)
}else{
setSlide(slideIdx - 1)
}
}
if (val === 1){
if (slideIdx === slides.length - 1){
setSlide(0)
}else{
setSlide(slideIdx + 1)
}
}
}
return (
<div>
<div id="navigation" className="text-center">
<button onClick={() => setSlide(0)} data-testid="button-restart" className="small outlined">
Restart
</button>
<button onClick={() => updateIndex(-1)} data-testid="button-prev" className="small">
Prev
</button>
<button onClick={() => updateIndex(1)} data-testid="button-next" className="small">
Next
</button>
</div>
<div id="Whatyouwant" className="card text-center">
<h1 data-testid="title">{slides[slideIdx].title}</h1>
<p data-testid="text">{slides[slideIdx].text}</p>
</div>
</div>
);
}
这里的问题是setSlide(slideShow[0])
。最初状态是用一个名为 slides
的数组初始化的。但是在 useEffect
中,状态正在用一个对象更新。所以,现在 slideShow
不再是 array
,而是 object
。因此 object.map
正在破坏应用程序。
useEffect(() => {
setSlide(slideShow[0]);
console.log("slides", slideShow[0]);
}, []);
下面是您正在寻找的操作类型的示例。我没有将 slides
存储在状态中,而是在 state
中添加了项目的 index
并相应地对其进行了更新。
const SLIDES = [{title:"Today's workout plan",text:"We're gonna do 3 fundamental exercises."},{title:"First, 10 push-ups",text:"Do 10 reps. Remember about full range of motion. Don't rush."},{title:"Next, 20 squats",text:"Squats are important. Remember to keep your back straight."},{title:"Finally, 15 sit-ups",text:"Slightly bend your knees. Remember about full range of motion."},{title:"Great job!",text:"You made it, have a nice day and see you next time!"}];
const { useState, useEffect } = React;
function Slides({ slides }) {
const [selectedIndex, setSelectedIndex] = useState(0);
const previous = () => {
if(selectedIndex !== 0) {
setSelectedIndex(index => index-1);
}
}
const next = () => {
if(selectedIndex !== slides.length - 1) {
setSelectedIndex(index => index+1);
}
}
const restart = () => {
setSelectedIndex(0);
}
return (
<div>
<div id="navigation" className="text-center">
<button data-testid="button-restart" className="small outlined" onClick={restart}>
Restart
</button>
<button data-testid="button-prev" className="small" onClick={previous}>
Prev
</button>
<button data-testid="button-next" className="small" onClick={next}>
Next
</button>
</div>
<div className="card text-center">
<h1 data-testid="title">{slides[selectedIndex].title}</h1>
<p data-testid="text">{slides[selectedIndex].text}</p>
</div>
</div>
);
}
ReactDOM.render(<Slides slides={SLIDES}/>, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="react"></div>
注意:在这里,对于所有三个操作,我们可以只有一个函数,为了简单起见,我创建了三个不同的函数来更新幻灯片索引。
我正在尝试通过道具将以下数据传递给 Slide.js
来制作幻灯片应用程序。
const SLIDES = [
{
title: "Today's workout plan",
text: "We're gonna do 3 fundamental exercises."
},
{
title: "First, 10 push-ups",
text: "Do 10 reps. Remember about full range of motion. Don't rush."
},
{
title: "Next, 20 squats",
text: "Squats are important. Remember to keep your back straight."
},
{
title: "Finally, 15 sit-ups",
text: "Slightly bend your knees. Remember about full range of motion."
},
{
title: "Great job!",
text: "You made it, have a nice day and see you next time!"
}
];
我的子组件Slide.js
具有以下代码
import React, { useState, useEffect } from "react";
function Slides({ slides }) {
const [slideShow, setSlide] = useState(slides);
useEffect(() => {
setSlide(slideShow[0]);
console.log("slides", slideShow[0]);
}, []);
return (
<div>
<div id="navigation" className="text-center">
<button data-testid="button-restart" className="small outlined">
Restart
</button>
<button data-testid="button-prev" className="small">
Prev
</button>
<button data-testid="button-next" className="small">
Next
</button>
</div>
{slideShow.map((slide, i) => (
<div id={i} className="card text-center">
<h1 data-testid="title">{slide.title}</h1>
<p data-testid="text">{slide.text}</p>
</div>
))}
</div>
);
}
export default Slides;
我认为使用 setSlide(slideShow[0])
只会在应用程序初始加载后呈现对象数组中的第一项。但是我得到
TypeError: slideShow.map is not a function
但是当我console.log("slides", slideShow[0])
我输出
slides {title: "Today's workout plan", text: "We're gonna do 3 fundamental exercises."}
如果我将代码更改为
setSlide(slideShow.slice(0, 1));
该应用程序仅显示数组中的第一个对象,但如果我 console.log("slides", slideShow)
,即使我认为我应该收到切片版本,我也会得到整个对象数组。
我的 map
函数是否没有引用 slideShow[0]
导致错误发生?
useState 本质上是异步的,但不是 return 承诺,但要解决 useState 的异步性质和快速肮脏的修复方法就是对您的数据进行空传播,例如
幻灯片?.地图
但我会怎么做,就像这样: 只是给你一些想法
import SLIDES from ....slides.etc
const [slideIndex, setSlideIndex]=useState(0)
<item onClick={()=>{setSlideIndex(slideIndex + 1)}} >
{SLIDES[slideIndex]}
</item>
举个例子给大家参考
引用此行时出现错误slideShow.map((slide, i) => (
问题在于您的 useEffect 在您的组件呈现后被调用,并且您将幻灯片放映设置为单张幻灯片 slideShow[0]
。然后您继续 re-render 您的组件,并尝试映射到 slideShow,但幻灯片等于原始幻灯片变量 (slideshow[0]
) 的第一项并且您无法映射到单个幻灯片.
您可能希望将代码编辑得更像
function Slides({ slides }) {
const [slideIdx, setSlide] = useState(0);
const updateIndex = (val) => {
if (val === -1){
if (slideIdx === 0){
setSlide(slides.length -1)
}else{
setSlide(slideIdx - 1)
}
}
if (val === 1){
if (slideIdx === slides.length - 1){
setSlide(0)
}else{
setSlide(slideIdx + 1)
}
}
}
return (
<div>
<div id="navigation" className="text-center">
<button onClick={() => setSlide(0)} data-testid="button-restart" className="small outlined">
Restart
</button>
<button onClick={() => updateIndex(-1)} data-testid="button-prev" className="small">
Prev
</button>
<button onClick={() => updateIndex(1)} data-testid="button-next" className="small">
Next
</button>
</div>
<div id="Whatyouwant" className="card text-center">
<h1 data-testid="title">{slides[slideIdx].title}</h1>
<p data-testid="text">{slides[slideIdx].text}</p>
</div>
</div>
);
}
这里的问题是setSlide(slideShow[0])
。最初状态是用一个名为 slides
的数组初始化的。但是在 useEffect
中,状态正在用一个对象更新。所以,现在 slideShow
不再是 array
,而是 object
。因此 object.map
正在破坏应用程序。
useEffect(() => {
setSlide(slideShow[0]);
console.log("slides", slideShow[0]);
}, []);
下面是您正在寻找的操作类型的示例。我没有将 slides
存储在状态中,而是在 state
中添加了项目的 index
并相应地对其进行了更新。
const SLIDES = [{title:"Today's workout plan",text:"We're gonna do 3 fundamental exercises."},{title:"First, 10 push-ups",text:"Do 10 reps. Remember about full range of motion. Don't rush."},{title:"Next, 20 squats",text:"Squats are important. Remember to keep your back straight."},{title:"Finally, 15 sit-ups",text:"Slightly bend your knees. Remember about full range of motion."},{title:"Great job!",text:"You made it, have a nice day and see you next time!"}];
const { useState, useEffect } = React;
function Slides({ slides }) {
const [selectedIndex, setSelectedIndex] = useState(0);
const previous = () => {
if(selectedIndex !== 0) {
setSelectedIndex(index => index-1);
}
}
const next = () => {
if(selectedIndex !== slides.length - 1) {
setSelectedIndex(index => index+1);
}
}
const restart = () => {
setSelectedIndex(0);
}
return (
<div>
<div id="navigation" className="text-center">
<button data-testid="button-restart" className="small outlined" onClick={restart}>
Restart
</button>
<button data-testid="button-prev" className="small" onClick={previous}>
Prev
</button>
<button data-testid="button-next" className="small" onClick={next}>
Next
</button>
</div>
<div className="card text-center">
<h1 data-testid="title">{slides[selectedIndex].title}</h1>
<p data-testid="text">{slides[selectedIndex].text}</p>
</div>
</div>
);
}
ReactDOM.render(<Slides slides={SLIDES}/>, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="react"></div>
注意:在这里,对于所有三个操作,我们可以只有一个函数,为了简单起见,我创建了三个不同的函数来更新幻灯片索引。