简体   繁体   中英

Setting state inside of axios function call, then call function in useEffect hook

I am using React functional components. I am setting state inside of an axios call, then calling the function in useEffect hook.

Here is my function:


import { useDispatch } from “react-redux”;

functon ABCComponent({ navigation }){

    const dispatch = useDispatch();
   
    const testPostID = "1234567891011";
    
    const [post, setPost] = useState("");

     const getPostById = async(postID)=>{
        await axios.get(`http://localhost:5000/posts/post/${postID}`)
            .then((response) =>{
                dispatch(setLoading(true));
                dispatch(setSuccess(true));
                dispatch(setLoading(false));
                response.data.message.map((post, index) =>{
            
                    setPost(post); // I think it's complaining about this line
                });
            }).catch((error) =>{
                console.log("err: ", error);
                dispatch(setLoading(true));
                dispatch(setSuccess(false));
                dispatch(setLoading(false));
                dispatch(setMessage(`${error}`));
            });
    };

    useEffect(() =>{
        getPostById(testPostID);
    }, []);
    
}

I am getting the following error:

Warning : Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in %s.%s, a useEffect cleanup function, in ABCComponent.

What I tried: I tried removing async/await hoping that it would solve the problem, but it didn't.

what is the best way to go about solving this?

Memory leak can occur when you are trying to update state on unmounted component, like the warning said. In order to fix this you should include some isMounted flag that you will use in order to check whether component is still mounted, before updating state. Also there are few other suggests I would give you - do not use async/await with .then, you should use only one of these two approach(async/await is my suggestion).

You should rewrite to something like this:

const isMounted = useRef(true);
const testPostID = "1234567891011";

const [post, setPost] = useState("");

const getPostById = async(postID)=>{
      try {
        dispatch(setLoading(true));

        const response = await axios.get(`http://localhost:5000/posts/post/${postID}`)
        
        if(isMounted.current){
            dispatch(setSuccess(true));
            dispatch(setLoading(false));
            response.data.message.map((post, index) =>{
                 setPost(post); // This part is unclear, why overriding state, and why in .map???
            });
         }
       } catch(err) {
         console.log("err: ", error);
         if(isMounted.current) {              
           dispatch(setLoading(true));
           dispatch(setSuccess(false));
           dispatch(setLoading(false));
           dispatch(setMessage(`${error}`));
         }
       }
  };

useEffect(() =>{
    getPostById(testPostID);

   return () => {
     isMounted.current = false;
   }
}, []);

Also there is one unclear part where you are updating state, why using .map and why overriding state in each iteration?

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