React-hooks->useEffect

127 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 16天,点击查看活动详情

上一篇文章我们说到useState的改变不能同步的这个数据,所以官方给出了一个可以捕获到改变后的hooks,叫useEffect.

useEffect是什么

React 官方文档解释:Effect Hook 可以让你在函数组件中执行 副作用 操作. 而其中useState的改变就属于副作用的一种.

import React, { useState } from 'react';

function App() {
  const [data, setData] = useState({ hits: [] });

  return (
    <ul>
      {data.hits.map(item => (
        <li key={item.objectID}>
          <a href={item.url}>{item.title}</a>
        </li>
      ))}
    </ul>
  );
}

export default App;

就比如这个例子,我们就可以使用useEffect这个hooks来获取到data的变化.

 useEffect(()=>{
     // 改变后的操作
 },[data])

useEffect的参数

  • 这个函数的目的就是为了告诉 React 组件需要在渲染后执行哪些操作,这个函数会在DOM更新之后被调用,use Effect 默认在每次渲染之后都会执行。但是也可以手动控制它的执行。
  • 当数组中的任意一项变化的时候,useEffect会被重新执行 

如果传递一个空数组 [ ],告诉 useEffect 不依赖于 state、props中的任意值, useEffect 就只会运行一次,如果数组中有值,那么只有当依赖的值发生改变后才会执行函数.

用途

自定义hooks

比如我们可以将请求数据的代码自己封装成一个hooks.


 useEffect(() => {
    const fetchData = async () => {
      setIsError(false);
      setIsLoading(true);

      try {
        const result = await axios(url);

        setData(result.data);
      } catch (error) {
        setIsError(true);
      }

      setIsLoading(false);
    };

    fetchData();
  }, [url]);

  const doFetch = () => {
    setUrl(`http://localhost/api/v1/search?query=${query}`);
  };

  return { data, isLoading, isError, doFetch };
}

在自定义的hooks抽离完成后,引入到组件中, 就这样使用:

const { data, isLoading, isError, doFetch } = useHackerNewsApi();

那么请求数据的逻辑和展示页面的逻辑就完全分开了.

取消数据请求

React中的一种很常见的问题是:如果在组件中发送一个请求,在请求还没有返回的时候卸载了组件,这个时候还会尝试设置这个状态,会报错。我们需要在hooks中处理这种情况,可以看下是怎样处理的:

const useDataApi = (initialUrl, initialData) => {
  const [url, setUrl] = useState(initialUrl);

  const [state, dispatch] = useReducer(dataFetchReducer, {
    isLoading: false,
    isError: false,
    data: initialData,
  });

  useEffect(() => {
    let didCancel = false;

    const fetchData = async () => {
      dispatch({ type: 'FETCH_INIT' });

      try {
        const result = await axios(url);

        if (!didCancel) {
          dispatch({ type: 'FETCH_SUCCESS', payload: result.data });
        }
      } catch (error) {
        if (!didCancel) {
          dispatch({ type: 'FETCH_FAILURE' });
        }
      }
    };
  fetchData();

    return () => {
      didCancel = true;
    };
  }, [url]);

  const doFetch = url => {
    setUrl(url);
  };

  return { ...state, doFetch };
};

取消数据请求的操作很常见,但是大多数都是使用再确认的方式提示用户而不是添加一个取消按钮.