Home > Enterprise >  React Hook for a POST call onClick
React Hook for a POST call onClick

Time:11-04

I have a button, onClick of that button I want to make a POST call with some data user has filled in an input field, stored in state, and then redirect the user to another page.

My current code looks like this, but I get an error:

React Hook "usePost" is called in function "onAccept" which is neither a React function component or a custom React Hook function

And the code doesn't work. I have created my own hook for POST calls.

What might a way to make the desired functionality work?

What I'm after is the ability to make a POST call and redirect.

Simplified example:

// my function
const onAccept = () => {
  const { data, loading, error } = usePost(
    "MY_URL",
    { DATA: MY_DATA }
  );
  if (data && !error) {
    navigate(`/`);
  }
};

// return
<button onClick={() => onAccept()}

CodePudding user response:

Yes, You are calling usePost hook inside of onAccept function. You should follow react hook rule.

To solve your problem, you can do like that:

your custom hook file:

export const usePost = () => {
  const [status, setStatus] = useState()

  const handlePost = useCallback(async (url, data) => {
    // your api request logic in here, bellow only show example
    try {
      const {data, status} = await apiCall(url, data)
      if (data && status === 200) navigate(`/`)
    } catch (error) {
      console.log(error)
    }
  }, [])

  return { handlePost }
  // to return status to component, you can use bellow.
  // return { status, handlePost }
}

then your component:

const YourComponent: React.FC = () => {
  const { handlePost } = usePost()
  // To get status: const { status, handlePost } = usePost()
  // your other hooks in here
  // Check status
  useEffect(() => {
    if (status === 200) {
      // whatever you want to do
    }
  }, [status])
  
  return (
    <>
      // Your component UI here
      ...
      <button onClick={() => handlePost(url, data)}>
    </>
  )
}

You should call your custom hooks(for example: usePost) at the top level of component, not nested function body as like as you were doing in your code (onAccept function body).

CodePudding user response:

I can suggest you do the following.

At first, you should create fetch function which will be returned from usePost hook.

example.

export const usePost = () => {
  const [loading, setLoading] = useState(false)
  const [data, setData] = useState([])

  const fetch = () => {
    setStatus(loading)
    apiRequest({
      url: 'my_url',
      method: 'GET',
   
    }).then(response => {
      setStatus(false)
      setData(response.data.data)
    }).catch(e => {
      setStatus(false)
    })
  }

  return {
    status,
    data,
    fetch
  }

After all, you can call this hook in your component. It will return fetch function. You should call fetch inside onAccept.

Example.

const { data, loading, fetch } = usePost()

const onAccept = () => {
    fetch()
 }

// return
<button onClick={() => onAccept()}

   

PS. if you need you can return errors from usePost hook, as well.

CodePudding user response:

First, call you hook from React Function. Read the docs: https://reactjs.org/docs/hooks-rules.html#only-call-hooks-from-react-functions.

Second, you should have some sort of load method in your usePost hook, e.g.: const { load } = usePost(...), in order to make POST request on click.

So your handler will look like:

const onAccept = () => {
  load();

  // the following block move somewhere before you render the component or better use useEffect hook for that
  // if (data && !error) {
  //   navigate(`/`);
  // }
};

I hope this will help.

  • Related