在我的代码示例中,我的 useEffect 订阅了 postId,它在任何时候都不会改变。然而 useEffect 仍在运行。
有没有办法阻止它运行并且只有在我更改它时才启动?
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
答案 0 :(得分:1)
事实上,在第一次运行中,postId
为空,因为您以这种方式对其进行了初始化。所以你也需要注意这一点。
useEffect
要么接受依赖项数组,要么您可以将其留空。在后一种情况下,它只运行一次,因为没有依赖项,但在第一种情况下,它既侦听依赖项变化,也在第一次挂载组件时运行。
useEffect(()=>{
if (postId == null) return;
...
}, [postId]);
对于更通用的方法,您可以使用如下所示的方法。
const [ready, setReady] = useState(false);
useEffect(() => {
setReady(true);
}, [])
useEffect(()=>{
if (!ready) return;
...
}, [postId, ready]);
上述解决方案在大多数情况下都足够公平,但我建议您通过创建 ref 来处理它,将其分配给您的 DOM 元素,然后等待该 ref 可用。所以你确定你的组件是第一次被渲染。
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>
这样你就不需要额外的重新渲染,因为更新引用不会导致重新渲染。