编写hooks的时候,有遇到一个问题,是否可以将useEffect里面获取到的数据进行返回?

在编写hooks的时候,有遇到一个问题,是否可以将useEffect里面获取到的数据进行返回?

export const useGetWorkData = () => {


  const { workDone } = useStore()

  useEffect(() => {

    const asyncFunc = async () => {
      if(workDone) {
    const resultData = await fetchData(workDone.id)  // 想要返回:resultData 这个值
      }
    }
    asyncFunc()
  }, [workDone])


  // 这里想要返回在useEffect里面获取到的resultData,请问应该如何做呢?(要求必须要等到workDone有值进行返回)
  return resultData
}

目前的疑问就是:
1、是否将useEffect获取到的数据进行返回呢?
2、我能想到的办法就是hook下定义一个变量,在useEffect中进行接受,然后返回这个变量。
但是这里的疑问就是,如何确保返回的hook是在useEffect执行完成之后赋予了值的返回?
3、是否可以进行等待workDone有值了(最开始workDone没有值,在App.ts有初始化之后才会进行返回),才返回。

阅读 613
4 个回答

问题1
可以通过 useState 和 useEffect 结合来实现。useEffect 中获取到的数据可以通过 useState 存储,并在 Hook 中返回这个状态。

问题2
使用 useState 来存储数据,并在 useEffect 中更新状态。React 会在状态更新后重新渲染组件,确保返回的数据是最新的。

问题3
可以在 useEffect 中检查 workDone 是否有值,然后再进行数据获取和状态更新。初始状态可以设置为 null 或者其他合适的默认值,表示数据尚未获取到。

import { useState, useEffect } from 'react';
import { useStore } from './store'; // 假设 useStore 是从某个文件中导入的

export const useGetWorkData = () => {
  const { workDone } = useStore();
  const [resultData, setResultData] = useState(null);

  useEffect(() => {
    const asyncFunc = async () => {
      if (workDone) {
        const result = await fetchData(workDone.id);
        setResultData(result);
      }
    };
    asyncFunc();
  }, [workDone]);

  return resultData;
};
export const useGetWorkData = () => {


  const { workDone } = useStore()
const [data,setData]=useState()
  useEffect(() => {

    const asyncFunc = async () => {
      if(workDone) {
    const resultData = await fetchData(workDone.id)  // 想要返回:resultData 这个值
setData(resultData)
      }
    }
    asyncFunc()
  }, [workDone])


  // 这里想要返回在useEffect里面获取到的resultData,请问应该如何做呢?(要求必须要等到workDone有值进行返回)
  return data
}
  1. 不可以;
  2. 不是在 hook 里定义变量,而是在 hook 外定义一个 const ref = useRef(),用 ref.value 来暂存你需要保存的值(useState 也能保存,但对于任何无需触发组件更新的内容,都不建议使用 useState);
  3. 你已经将 workDone 添加到 useEffect 的依赖列表里,所以自然是可以的,if(workDone)已经保证了这一点,但是需要处理可能的闭包陷阱(经久不用,忘了有没有闭包陷阱了);
  4. 实际上,应该直接在 useEffect 里直接处理 resultData,而不是直接想着把它暴露出来。

大抵如此:

const ref = useRef();
const effect = useFunction(async () => {
  if(!workDone) return;
  ref.value = await fetchData(workDone.id);
})

if(ref.value){
  // ref.value 有值的时候就会执行这里的代码,且每次组件更新都会执行
}

自定义Hook:

import { useState, useEffect } from 'react';

export const useGetWorkData = () => {
  const [resultData, setResultData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);
  
  const { workDone } = useStore();

  useEffect(() => {
    const fetchWorkData = async () => {
      try {
        setIsLoading(true);
        setError(null);
        
        if (workDone) {
          const data = await fetchData(workDone.id);
          setResultData(data);
        }
      } catch (err) {
        setError(err);
      } finally {
        setIsLoading(false);
      }
    };

    fetchWorkData();
  }, [workDone]);

  return { 
    data: resultData, 
    isLoading, 
    error 
  };
};

用的时候

const MyComponent = () => {
  const { data, isLoading, error } = useGetWorkData();

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (!data) return <div>No data available</div>;

  return <div>{/*  data  */}</div>;
};

或者用async hook

import { useState, useEffect } from 'react';

export const useGetWorkData = () => {
  const [state, setState] = useState({
    data: null,
    isLoading: true,
    error: null
  });
  
  const { workDone } = useStore();

  const loadData = async () => {
    if (!workDone) {
      setState(prev => ({ ...prev, isLoading: false }));
      return;
    }

    try {
      const data = await fetchData(workDone.id);
      setState({
        data,
        isLoading: false,
        error: null
      });
    } catch (err) {
      setState({
        data: null,
        isLoading: false,
        error: err
      });
    }
  };

  useEffect(() => {
    loadData();
  }, [workDone]);

  const reload = () => {
    setState(prev => ({ ...prev, isLoading: true }));
    loadData();
  };

  return { ...state, reload };
};
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏