如何将 useEffect 从组件移动到自定义钩子

时间:2021-03-29 08:06:50

标签: reactjs react-hooks

我有多个具有相同 useEffect 代码的组件。

fucntion MyComponent1 (props) {

 const {
        handleApiCall,
        data,
        isLoading,
        isError,
        isSuccess,
  } = useCustomAsyncHook();

 React.useEffect(() => {
   if (isSuccess && !isEmpty(data)) {
      setSnackbar({
        show: false,
        message: '',
      });
      dispatch({
        type: ACTION_TYPES.UPDATE_METADATA,
        payload: { data },
      });
    }
 }, [data, isSuccess, setSnackbar]);

 const onSave = () => {
     handleApiCall()
 }

 return (
   <button onClick={onSave}> Save </button>
 )

}

我有这个 useEffect 钩子代码在多个组件中重复。 我只是想将这个 useEffect 钩子移动到自定义钩子中,这样我就不需要在多个组件中重复它了。

const useMetadataUpdate = ({ data, isSuccess, setSnackbar, dispatch }) => {
    React.useEffect(() => {
        if (isSuccess && !isEmpty(data)) {
            setSnackbar({
                show: false,
                message: '',
            });
            dispatch({
                type: ACTION_TYPES.UPDATE_METADATA,
                payload: { data },
            });
        }
    }, [data, isSuccess, setSnackbar, dispatch]);
};

fucntion MyComponet1 (props) {
   const {
        handleApiCall,
        data,
        isLoading,
        isError,
        isSuccess,
  } = useCustomAsyncHook();

  useMetadataUpdate({ data, isSuccess, setSnackbar, dispatch });

  const onSave = () => {
     handleApiCall()
 }

 return (
   <button onClick={onSave}> Save </button>
 ) 
}

useEffect 重构为单独的函数有效。 我找不到明确说明钩子需要返回任何内容的文档,但是,我找不到钩子不返回任何内容的示例。有人可以建议这种方法是否正确吗?

1 个答案:

答案 0 :(得分:0)

我在此处看到的当前问题是您有 3 个函数,即 isEmptysetSnackbardispatch 与此处的组件紧密耦合。这会限制您直接将此 useEffect 移动到您的自定义挂钩。我现在能想到的最佳解决方案是将这些函数移动到自定义钩子(您也可以将其与上下文 API 结合使用)。之后,您可以在自定义钩子中执行以下操作

const useCustomAsyncHook = () => {
  // code to fetch dependenices like `data`, `isSuccess` goes here

  const { setSnackbar, isEmpty, dispatch } = useAnotherCustomHook();

  React.useEffect(() => {
    if (isSuccess && !isEmpty(data)) {
       setSnackbar({
         show: false,
         message: '',
       });
       dispatch({
         type: ACTION_TYPES.UPDATE_METADATA,
         payload: { data },
       });
     }
  }, [data, isSuccess, setSnackbar]);
};