简体   繁体   中英

Eslint hook refactor useEffect

I create useEffect like that. I want useEffect listen useToken and when I login and set token it will fetch some data

  useEffect(() => {
    if (userToken) {
      setTimeout(() => {
        fetchDataWishlistShow();
        fetchCart();
      }, 500);
    }
    fetchCategory();
  }, [userToken]);

But Eslint of hook automatic add some function to Effect

  useEffect(() => {
    if (userToken) {
      setTimeout(() => {
        fetchDataWishlistShow();
        fetchCart();
      }, 500);
    }
    fetchCategory();
  }, [fetchCart, fetchCategory, fetchDataWishlistShow, userToken]);

Why it do that. I think it wrong but anyone can explain for me?

I guess you installed "eslint-plugin-react-hooks" and enable it.

useEffect is designed the way that which ever you use in you useEffect you are recommended to add it it dependencies array list EXCEPT some things that React guarantee that they are not changed every each re-render such as: dispatch of useReducer, setState form const [state, setState] = useState() or functions or variables imported from other files.

You can turn off the rule but you SHOULD NOT do that because you did not solve the source of the problem. Eg

const [cartStatus, setCartState] = useState("all") // assume it can be "all", "pending"

const fetchCart = () =>{
   fetch(`endpoint/cart/${cardStatus}`)
}

useEffect(() => {
    if (userToken) {
      setTimeout(() => {
        fetchDataWishlistShow();
        fetchCart();
      }, 500);
    }
    fetchCategory();
    // This case you alway fetch all item in cart
  }, [userToken]);

To fix issue above you saying you saying, yeah we can just add fetchCart into dependency list, but it'll cause infinite re-render, you need to wrap fetchCart by useCallback or move fetchCart into useEffect . Because you call the function inside setTimeout, you might want to clean the useEffect

const [cartStatus, setCartState] = useState("all") // assume it can be "all", "pending"


useEffect(() => {
   const fetchCart = () =>{
     fetch(`endpoint/cart/${cardStatus}`)
   }
   let id = null
    if (userToken) {
      id = setTimeout(() => {
        fetchDataWishlistShow();
        fetchCart();
      }, 500);
    }
    fetchCategory();
    return () => clearTimeout(id);  
  }, [userToken]);

This article is written by Dan Abramov is a good resource to look at and deep dive into how useEffect works and why you should follow the recommended way.

You might saying that "No no, I am only have api call when the component mounted, That's it". But when your project grown, and you components become complicated, it's hard to remember that, who's know that your requirements might be changed at some point in the future, why don't do it in proper way to give you more confident when refactor or update your components?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM