【问题标题】:How to call a function in useEffect only after getting data from backend?仅在从后端获取数据后如何在 useEffect 中调用函数?
【发布时间】:2021-07-14 16:07:38
【问题描述】:

我必须实现的是从第一次渲染本身按排序顺序显示从 api 响应获得的数据。

这就是我使用 useEffect 挂钩的方式:-

useEffect(()=>{
        async function fetchProject() {
            await axios.post(envurls.wv+'/show_project',{
                params:{
                    authtoken:authtoken,
                    user:user
                }
            }).then((response)=>{
                console.log('Res', response.data);
                setShowProject(response.data)
                
            }).catch((error)=>{
                console.log(error)
            })
        }
        fetchProject();
        
    },[]);

    useEffect(() => {
        showProject.length> 0 && sortArray();
    }, []); 

   
    const sortArray = ()=> {
        const sortProperty = 'timestamp';
     
        sorted = [...showProject].sort((a, b) => (a[sortProperty] > b[sortProperty] ? -1 : 1))
        console.log("Project", showProject);
        console.log("Sorted Data", sorted);
        setShowProject(sorted);
    };

但在第一次渲染时,它不会对数据进行排序,因为 showProject 数组是空的。所以,我在控制台上将项目和排序数据作为空数组。

如果我像这样在 useEffect 中提供 showProject:-

useEffect(() => {
    showProject.length> 0 && sortArray();
}, [showProject]); 

然后它为第一次渲染本身显示排序数据,但项目和排序数据在控制台中显示 n 次。

【问题讨论】:

  • 为什么排序数组函数需要在useEffect中?此外,由 fetch 填充的状态将在第一次渲染时始终是默认状态
  • 收到后不能排序吗?
  • 因为,我必须根据其他状态对数据进行排序,例如排序类型“asc”或“desc”。所以每次用户从 asc 切换到 desc。 sortArray 应该被调用。所以我在这里将 [sortType] 作为第二个参数传递给 sortArray 的 useEffect
  • 如果 useEffect 依赖于状态 showProject 那么它应该被放入依赖数组中。此外,您没有将任何内容传递给sortArray
  • 我试图通过 showProject 但它在控制台中显示数据 n 次。我忘了在这里添加它。我只是编辑了代码。

标签: javascript reactjs async-await react-hooks use-effect


【解决方案1】:

您可以使用useMemo,并将依赖关系设置为状态中的数据和排序参数。

useMemo 将在其中一个依赖项发生变化时调用该函数,与useEffect 完全相同,但这次它将返回我们从该函数返回的值。

这样我们就不会触碰原始状态,只是在变化后进行排序

useEffect(() => {
  async function fetchProject() {
    const { data } = await axios.post(envurls.wv + "/show_project", {
      params: {
        authtoken: authtoken,
        user: user
      }
    });

    setShowProject(data);
  }

  fetchProject().catch(e => /* handle error here */);
}, []);

const sorted = useMemo(() => {
  const sortProperty = "timestamp";

  // use the sorting parameters here

  return [...showProject].sort((a, b) =>
    a[sortProperty] > b[sortProperty] ? -1 : 1
  );
}, [showProject, sortType]);

console.log(sorted);

【讨论】:

  • 所以你创建了一个排序的备忘录,但由于它不是一个函数,如果想将 sortProperty 作为参数传递。
  • @AnkitJaishwal 您将sortProperty 保存在状态中或通过props 传递并将其包含在依赖项数组中。这样当你更新useMemo时会自动重新运行提供的功能。
  • 你也可以只在渲染中排序,但我认为useMemo 使它更干净,并且只会在需要时运行
【解决方案2】:

据我所知,在第一次渲染时获取“排序数据”的唯一方法是通过 props 将排序数据传递给组件。您还不必要地更新了您的 showProject 两次,这将导致不必要的重新渲染,@Asaf Aviv 的回答是一个很好的解决方法。

call a function only after getting data from the backend 的最佳方法是将函数调用放在 .then() 回调内部或在等待之后的 async 函数内部。现在你的sortArray() 没有做这些,它超出了你的async function 的范围,await 对它没有影响。组件渲染,检查showProject.length> 0 条件,如果满足条件,则运行函数。

另外,您不需要在异步函数中使用 .then().catch(),这是一种更典型的方法:

async function fetchProject() {
  try {
    let response = await axios.post(envurls.wv + "/show_project", {
      params: {
        authtoken: authtoken,
        user: user
      }
    });
    // everything past here runs ONLY AFTER getting a response back from axios.post
    setShowProject(response.data)
  } catch (err) {
    console.log(err);
  }
}
   

【讨论】:

    猜你喜欢
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 2019-06-07
    • 2023-01-21
    • 2022-01-21
    相关资源
    最近更新 更多