简体   繁体   中英

React | props inside UseCallBack not updating inside custom hook

I've build an custom custom post hook that returns the API response and the API post. And I am using useCallback hook to set the Response state

Where it goes wrong is that the Package prop doesn't update inside the useCallback hook.

When I log Package outside the useCallback hook I get the right data inside the propertie. However when I log the Package prop inside the useCallback hook the value of Package doesn't change.

No matter how many times I press the button

I've tried creating an order state that updates everytime the Package prop updates, however whenever I set Package as an value in the scope I get an infinite loop.

I've alos added Package into the scope of the useCallback hook

example

  React.useEffect(() => {
    setOrder(Package);
  }, [Package]);

What I expect to happen is that whenever I call my custom usePostOrder hook the value of Package that is inside the useCallback is always up to date with the latest passed on prop.

CustomHook

/**
 * custom post hook that returns the API response and the API post function
 * @param {string} url
 * @param {object} Package
 * @returns {array} and @param {function}
 */

export const usePostOrder = (url, Package) => {
  const [loading, setLoading] = React.useState(true);
  const [order, setOrder] = React.useState(Package);
  const [response, setResponse] = React.useState({
    config: {
      data: []
    },
    data: {
      id: 0
    }
  });

  console.log("outside func", Package);
  const postOrder = React.useCallback(async () => {
    console.log("inside func", Package);
  }, [url, loading, Package]);

  return [response, postOrder];
};

Answer by Jake Luby with a slight adjustment

/**
 * custom post hook that returns the API response and the API post function
 * @param {string} url
 * @param {object} Package
 * @returns {array} and @param {function}
 */

export const usePostOrder = (url, Package, send) => {
  const [postOrder, setPostOrder] = React.useState();
  const [response, setResponse] = React.useState({
    config: {
      data: []
    },
    data: {
      id: 0
    }
  });

  React.useEffect(() => {
    const getData = async send => {
      //this will have the updated input Package
      await axios
        .post(ApiUrl + url, Package)
        .then(function(response) {
          setResponse(response);
        })
        .catch(function(error) {
          setResponse(error);
          console.log(error);
        });
    };

    send && getData();
  }, [send]); //this will run when url or Package changes

  return [response, postOrder];
};

useAsyncEndpoint.PropTypes = {
  url: PropTypes.url,
  user: PropTypes.object,
  club: PropTypes.object,
  cartItems: PropTypes.array
};

How I call this hook

import {usePostOrder} from "./yourHooksFolder"
  const [send, setSend] = React.useState(false);
  const [response, postOrder] = usePostOrder(
    "url",
    createOrder(user, store, cartItems),
    send
  );

  React.useEffect(() => {
    setSend(false);
  }, [response]);

// send order
  const onGoToPaymentPressed = () => {
    setSend(true);
  };



useCallback is not meant to be used like that. It doesn't actually run the function, it simply memoizes it so that between renders the same function isn't recreated.

What you want is the useEffect hook and to have the postOrder as part of the state:

export const usePostOrder = (url, Package) => {
  const [postOrder, setPostOrder] = React.useState()
  const [response, setResponse] = React.useState({
    config: {
      data: []
    },
    data: {
      id: 0
    }
  })


  React.useEffect(() => {
    const getData = async url => {
        //this will have the updated input Package
        console.log(Package) 

        //here is where you'll have your REST calls

        //set your data which will then update the return values in the hook and cause a rerender
        setPostOrder(returnValue)
        setResponse(someResponse)
    }

    getData()
  }, [url, Package]) //this will run when url or Package changes

  return [response, postOrder]
}

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