Reputation: 29
Hi I am trying to create a function that is called when you click add to cart on a product page. This function is in a separate file and is imported to the product page and is called onClick. However, I receive this error that says Invalid Hooks Call. What am I doing wrong?
import {AuthContext} from '../context/auth'
import gql from 'graphql-tag'
import {Button} from 'semantic-ui-react'
import {useMutation} from '@apollo/react-hooks'
const AddtoCart = (id) => {
console.log(id) //id gets logged into the console here.
const [errors,setErrors] = useState({}) ////shows error right here <<
const {user} = useContext(AuthContext);
const[addtoCart,{loading}] = useMutation(ADDTOCART,{
update(_,result){
//TODO: remove this alert
alert('success')
},
onError(err){
alert('error')
},
variables:{
productID:id
}
})
if(user){
addtoCart(id)
}
else{
if(localStorage.getItem('cart')){
cart = JSON.parse(localStorage.getItem('cart'));
cart.unshift(id);
localStorage.removeItem('cart');
localStorage.setItem('cart', JSON.stringify(cart));
}else{
var cart = [id];
localStorage.setItem('cart', JSON.stringify(cart));
}
}
}
const ADDTOCART = gql`
mutation addtoCart($productID: ID!){
addtoCart(productID: $productID)
}
`
export default AddtoCart;```
Upvotes: 1
Views: 53
Reputation: 311
It looks like you are exporting AddToCart
and calling that from the onClick
? This will not work because useState
is being called from the wrong context. The difference is that this function isn't a React component itself. Calling the function inside of a React component isn't sufficient, hook calls need to happen either in a custom hook (called in a component) or in a component.
If you want to have the function you're using modify state, then you can pass the setErrors
function to it as an argument, and have the call to useState
inside of the component that renders the button. You should do the same thing with the useMutation
and useContext
.
I would recommend lifting the hooks into the wrapping component, and just pass user
to the related logic:
function addToCart(user, id) {
if(user){
addtoCart(id)
}
else {
if(localStorage.getItem('cart')) {
cart = JSON.parse(localStorage.getItem('cart'));
cart.unshift(id);
localStorage.removeItem('cart');
localStorage.setItem('cart', JSON.stringify(cart));
}
else {
var cart = [id];
localStorage.setItem('cart', JSON.stringify(cart));
}
}
}
This function could be called in the onClick
so long as you move the hooks calls into the scope of the container
I definitely recommend giving the rules of hooks a read. It does a better job than me explaining why you can't have a hook in a nested function.
Upvotes: 1