Javascript useEffect在初始负载上运行&;更新时-如何限制仅更改?
在我的代码示例中,我的useEffect订阅了postId,这在任何时候都不会改变。但useEffect仍在运行 有没有办法阻止它运行,并且只有在我更改它时才能启动Javascript useEffect在初始负载上运行&;更新时-如何限制仅更改?,javascript,reactjs,typescript,react-hooks,Javascript,Reactjs,Typescript,React Hooks,在我的代码示例中,我的useEffect订阅了postId,这在任何时候都不会改变。但useEffect仍在运行 有没有办法阻止它运行,并且只有在我更改它时才能启动 import React, {useState, useEffect} from 'react'; import Vim from './Vim'; import './Main.css'; function Main():JSX.Element { const [postId,updatePostId] = useSt
import React, {useState, useEffect} from 'react';
import Vim from './Vim';
import './Main.css';
function Main():JSX.Element {
const [postId,updatePostId] = useState<number|null>(null)
const [content, updateContent] = useState<string>('default text');
const apiUrl = 'http://127.0.0.1:8000/'
useEffect(()=>{
// Detect change in PostID & go download it.
// Ignore if we are coming from null->number
console.log('Why am I running?')
fetch(apiUrl+'get_post/'+postId)
.then(res=>res.json())
.then(result=>console.log(result))
},[postId])
function loadPost(pid:number):string|null{
// fetch from API, load post content
console.log('I can access:'+postId)
return null;
}
function backLinks():JSX.Element{
return(
<div className="backlinks">
</div>
)
}
return (
<div className='main'>
<Vim content={content} />
</div>
)
}
export default Main
import React,{useState,useffect}来自“React”;
从“/Vim”导入Vim;
导入“/Main.css”;
函数Main():JSX.Element{
常量[postId,updatePostId]=useState(null)
const[content,updateContent]=useState('defaulttext');
康斯特阿皮乌尔酒店http://127.0.0.1:8000/'
useffect(()=>{
//检测PostID中的更改并下载它。
//如果我们来自null->number,则忽略
console.log('我为什么在运行?')
获取(apirl+'get_post/'+posted)
.then(res=>res.json())
.then(result=>console.log(result))
},[posted])
函数loadPost(pid:number):字符串| null{
//从API获取,加载post内容
console.log('我可以访问:'+posted)
返回null;
}
函数反向链接():JSX.Element{
返回(
)
}
返回(
)
}
导出默认主
事实上,在第一次运行时,postId
是空的,因为您以这种方式初始化它。所以你也需要注意这一点
useffect
要么接受依赖项数组,要么将其保留为空。在后一种情况下,它只运行一次,因为没有依赖关系,但是在第一种情况下,它既侦听依赖关系的变化,也在组件第一次装载时运行
useEffect(()=>{
if (postId == null) return;
...
}, [postId]);
const isMounted = useRef(null);
useEffect(()=>{
if (!isMounted.current) return;
// do your fetch stuff here
fetch(apiUrl+'get_post/'+postId)
.then(res=>res.json())
.then(result=>console.log(result))
}, [isMounted]);
<div ref={isMounted}></div>
对于更一般的方法,您可以使用如下内容
const [ready, setReady] = useState(false);
useEffect(() => {
setReady(true);
}, [])
useEffect(()=>{
if (!ready) return;
...
}, [postId, ready]);
上述解决方案在大多数情况下都是合理的,但我建议您通过创建一个ref来处理它,将其分配给DOM元素,并等待该ref变为可用。因此,您可以确定组件是第一次渲染的
useEffect(()=>{
if (postId == null) return;
...
}, [postId]);
const isMounted = useRef(null);
useEffect(()=>{
if (!isMounted.current) return;
// do your fetch stuff here
fetch(apiUrl+'get_post/'+postId)
.then(res=>res.json())
.then(result=>console.log(result))
}, [isMounted]);
<div ref={isMounted}></div>
const isMounted=useRef(null);
useffect(()=>{
如果(!isMounted.current)返回;
//你在这儿取东西吗
获取(apirl+'get_post/'+posted)
.then(res=>res.json())
.then(result=>console.log(result))
},[isMounted]);
通过这种方式,您不需要额外的重新渲染,因为更新引用不会导致重新渲染。我有其他示例,其中初始状态可能与更新状态相同,也可能与更新状态不同,但我仍然希望它仅在更改时运行。还有比这更普遍的解决方案吗?
postId
的第一个“变化”是从未定义(我不是说值未定义
)到初始值(是的,null
是一个值)。这相当于componentDidMount()
。第二个更改是从null
更改为某个数字。如果要忽略这些更改,请忽略这些更改(并告诉您的效果尽早返回),但这就是useffect()
的工作方式。