Javascript 使用React钩子实现一个自增量计数器
代码如下:Javascript 使用React钩子实现一个自增量计数器,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,代码如下: 导出默认值({name}:Props)=>{ const[counter,setCounter]=useState(0); useffect(()=>{ 常量间隔=设置间隔(()=>{ 设置计数器(计数器+1); }, 1000); return()=>{ 间隔时间; }; }); 返回{counter}; }; 问题是每个setCounter触发器都会重新渲染,因此间隔会被重置并重新创建。这看起来很好,因为状态(计数器)一直在增加,但是当与其他挂钩组合时,它可能会冻结 正确的方法
导出默认值({name}:Props)=>{
const[counter,setCounter]=useState(0);
useffect(()=>{
常量间隔=设置间隔(()=>{
设置计数器(计数器+1);
}, 1000);
return()=>{
间隔时间;
};
});
返回{counter};
};
问题是每个setCounter
触发器都会重新渲染,因此间隔会被重置并重新创建。这看起来很好,因为状态(计数器)一直在增加,但是当与其他挂钩组合时,它可能会冻结
正确的方法是什么?在类组件中,使用实例变量保持间隔非常简单。您可以将空数组作为第二个参数提供给
useffect
,这样函数在初始渲染后只运行一次。由于闭包的工作方式,这将使计数器
变量始终引用初始值。然后,您可以使用函数版本的setCounter
来始终获得正确的值
示例
const{useState,useffect}=React;
函数App(){
const[counter,setCounter]=useState(0);
useffect(()=>{
常量间隔=设置间隔(()=>{
设置计数器(计数器=>计数器+1);
}, 1000);
return()=>{
间隔时间;
};
}, []);
返回{counter};
};
ReactDOM.render(
,
document.getElementById('root'))
);代码>
如前所述,可以使其useffect
回调只运行一次,并与componentDidMount
类似。在这种情况下,由于函数作用域的限制,有必要使用状态更新程序函数,否则更新的计数器
在setInterval
回调中不可用
另一种方法是在每次计数器更新时运行useffect
回调。在这种情况下,setInterval
应替换为setTimeout
,更新应限于计数器
更新:
export default ({ name }: Props) => {
const [counter, setCounter] = useState(0);
useEffect(() => {
const timeout = setTimeout(() => {
setCounter(counter + 1);
}, 1000);
return () => {
clearTimeout(timeout);
};
}, [counter]);
return <h1>{counter}</h1>;
};
导出默认值({name}:Props)=>{
const[counter,setCounter]=useState(0);
useffect(()=>{
常量超时=设置超时(()=>{
设置计数器(计数器+1);
}, 1000);
return()=>{
clearTimeout(超时);
};
},[柜台];
返回{counter};
};
正确的方法是只运行一次效果。因为在装载过程中,只需要运行一次效果,所以可以将空数组作为第二个参数传入以实现
但是,您需要更改设置计数器
以使用先前的计数器值
。原因是传递到setInterval
闭包中的回调仅在第一次渲染中访问计数器
变量,在随后的渲染中,它无法访问新的计数器
值,因为第二次未调用useffect()
<代码>计数器
在设置间隔
回调中始终具有值0
与您熟悉的setState
一样,状态挂钩有两种形式:一种是在更新状态下使用,另一种是在其中传递当前状态的回调形式。您应该使用第二种形式并读取setState
回调中的最新状态值,以确保在递增之前具有最新状态值
函数计数器(){
const[counter,setCounter]=React.useState(0);
React.useffect(()=>{
常量计时器=设置间隔(()=>{
设置计数器(prevCount=>prevCount+1);//{
清除间隔(计时器);
};
},[]);//传入空数组仅运行一次效果!
返回(
计数:{counter}
);
}
ReactDOM.render(,document.querySelector(“#app”);
这并不理想,因为每次渲染时都会运行setTimeout
,这似乎是不必要的。我看不出这有什么问题。性能问题不存在。递归setTimeout是JS中setInterval的常用替代品,只要它是合理的。在这个特定的c中,setInterval中的状态更新程序函数看起来不错ase,即简单增量。如果涉及多个状态,这将非常不同。
export default ({ name }: Props) => {
const [counter, setCounter] = useState(0);
useEffect(() => {
const timeout = setTimeout(() => {
setCounter(counter + 1);
}, 1000);
return () => {
clearTimeout(timeout);
};
}, [counter]);
return <h1>{counter}</h1>;
};