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.