useEffect 在初始加载和更新时运行 - 如何限制仅更改?

时间:2021-01-31 18:51:11

标签: 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] = 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

1 个答案:

答案 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>

这样你就不需要额外的重新渲染,因为更新引用不会导致重新渲染。