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 ponent 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()}
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 ponent 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()}
Share
Improve this question
edited Jan 26 at 19:12
VLAZ
29.1k9 gold badges63 silver badges84 bronze badges
asked Nov 4, 2022 at 13:21
matmikmatmik
6801 gold badge6 silver badges15 bronze badges
4
- 1 Did you read the error message? – morganney Commented Nov 4, 2022 at 13:26
- The error is pretty clear. You can't use custom hooks within functions. They have to be used in (at the top level) a ponent or another custom hook. – Andy Commented Nov 4, 2022 at 13:27
- Yes I read the error message, but I'm confused what the way to fix it would be? Do I get rid of the custom hook and paste the code from the hook to the onAccept function in order to make a post call? – matmik Commented Nov 4, 2022 at 13:29
- Thanks @Andy - does that mean that a "dynamic" use of the usePost through the onClick is not possible to achieve? Seems like a custom hook for making POST calls is not a thing then, as often the call contains data from a form / page otherwise? – matmik Commented Nov 4, 2022 at 13:33
3 Answers
Reset to default 4I 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 = () => {
setLoading(loading)
apiRequest({
url: 'my_url',
method: 'GET',
}).then(response => {
setLoading(false)
setData(response.data.data)
}).catch(e => {
setLoading(false)
})
}
return {
status,
data,
fetch
}
After all, you can call this hook in your ponent. 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.
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 ponent, you can use bellow.
// return { status, handlePost }
}
then your ponent:
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 ponent UI here
...
<button onClick={() => handlePost(url, data)}>
</>
)
}
You should call your custom hooks(for example: usePost
) at the top level of ponent, not nested function body as like as you were doing in your code (onAccept
function body).
First, call you hook from React Function. Read the docs: https://reactjs/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 ponent or better use useEffect hook for that
// if (data && !error) {
// navigate(`/`);
// }
};
I hope this will help.