I am trying to setAddedToCard(true); when the onClick button is clicked to show that the product is added to the cart but addedToCard is only true after the button is clicked twice. This is because checkItem === true is set upon first click, then retrieved during the second click.
How do I change the code so that addedToCard is true upon first click & maintain checkItem === true if the item was successfully added to the cart?
const [addedToCard, setAddedToCard] = useState(false);
const CampaignAdminAuthToken = localStorage.getItem("CampaignAdminAuthToken");
const user = useSelector((state) => state.user);
const dispatch = useDispatch();
const cart_btn = addedToCard ? (
<Button>
<FontAwesomeIcon icon={solid("circle-check")} />
</Button>
) : (
<Button
onClick={() => {
props.addToCart(productId, totalQuantity);
dispatch(setIsUpdateCart(!user.isUpdateCart));
}}
>
{props.currencySymbol + (totalPrice ? Number(totalPrice) : 0)}
</Button>
);
useEffect(() => {
(async () => {
setTotalPrice(productPrice.toFixed(2));
if (!CampaignAdminAuthToken) {
const checkItem = await props.checkItemInCart(productId);
if (checkItem === true) {
setAddedToCard(true);
} else {
setAddedToCard(false);
}
}
})();
}, [!user.isUpdateCart, productPrice]);
Related
I am new to react.
I have a Customer component which has a modal. After opening the modal there are two buttons on that Yes and cancel. Once the user clicks the yes button API will get called and then I will reload the screen. I need to test the modal's primary and secondary buttons.
export default function
Customer({customerInfo, reloadCustomerData}) {
const [visible, setVisible] = useState(false);
const [editCustomerModal, setEditCustomerModal] = useState(false);
const [customerData, setCustomerData] = useState({});
const [apiError, setApiError] = useState(null);
const[status, setStatus] = useState("");
const editCustomerRef = useRef(null)
useEffect(() => {
setCustomerData(customerInfo)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [customerInfo]);
function handleActivateAndDeactivate(status) {
setVisible(true)
setStatus(status)
}
async function updateCustomerStatus(status) {
let reqBody = {
"status": status
}
console.log("status req body", reqBody)
try {
await ApiClient.put(UrlBuilder().updateCustomer(customerData.customerId), reqBody).then(response => {
if (response.status === 200) {
setVisible(false)
reloadCustomerData()
}
})
} catch (respError) {
setApiError(respError);
}
}
return (
<div>
<Modal data-testid="testActivateAndDeactivateModal"
buttonPrimary={{
label: "Yes",
onClick: () => updateCustomerStatus(status)
}}
buttonSecondary={{
label: "Cancel",
onClick: () => setVisible(false)
}}
onDismiss={() => setVisible(false)}
title={status === 'ACTIVE' ? "Activate Customer" :"Deactivate Customer"}
visible={visible}
>
<Paragraph>{status === 'ACTIVE' ? "Are you sure you want to activate the customer?" : " Are you sure you want to de-activate the customer?\n" +
"Customer will not be able to place any orders or create any new accounts"}
</Paragraph>
</Modal>
</div>
)
}
I want to test if reloadCustomerdata is getting called or not after clicking primary button "Yes". How Can I achieve that?
I'm using React and I have a list, and each item in the list with a check.
And I want that when there is at least one check in true, a button is shown (it is to delete all the checks).
I am using useReducer() to store the list.
This is my code, but it doesn't work.
const init = () => {
return JSON.parse(localStorage.getItem('todos')) || [];
}
const [todos, dispatch] = useReducer(todoReducer, [], init)
const [todoDelete, setTodoDelete] = useState(0)
useEffect(() => {
localStorage.setItem('todos', JSON.stringify(todos));
todos.map(todo => {
todo.check ? setTodoDelete(todoDelete+1) : setTodoDelete(todoDelete-1);
})
}, [todos])
returm (
code...
{
(todoDelete!==0)
&& <button
className='btn btn-danger btn-sm h-50' onClick={handleDeleteChecked}>
Delete
</button>
}
)
What interests me is that when there is more than one check, a button is added, otherwise it is removed. How do i do it?
Change this
todo.check ? setTodoDelete(todoDelete+1) : setTodoDelete(todoDelete-1);
To this
todo.check ?? setTodoDelete(prev => prev+1);
I retrieve a list of jobs using useQuery(), each one have a Favourite icon (filled depending if it's favourited)
If I click that button, I managed to refresh the item Favourite icon, but it refreshes all the items.
Whats the correct way to avoid that? Because it appears the Loading wheel again, and I think it has to be a more elegant way.
const Openings = () => {
const onToggleFav = () => {
setFavCount(prev => prev + 1)
}
const [favCount, setFavCount] = useState(0);
const { isLoading, data } = useQuery(
['getRecruiterOpenings', favCount],
() => getRecruiterOpenings()
);
return (
<div>
{ isLoading ? <Loading /> : (
<>
{ data && data.openings && data.openings.map((opening) => (
<>
<Opening {...opening} onToggleFav={() => onToggleFav()} key={opening.id}/>
</>
))}
</>
)}
</div>
)
}
export default Openings;
Inside Opening component I have a method that dispatches when you click the fav icon:
const toggleFav = async (e) => {
e.preventDefault();
await toggleFavOpening(fav, id).then(() => {
if(onToggleFav) onToggleFav()
});
}
I have a button "Add to Cart" and I would like it to do two things when clicked. I want it to add an item to the cart and I also want it to Change the text to "added" for 1 second.
The problem is if I call onClick twice the second function overrides the first.
If I put both click handlers into 1 function and then call that in 1 single onClick the only the function adding things to the cart works.
Where am I going wrong?
const [variant, setVariant] = useState({ ...initialVariant })
const [quantity, setQuantity] = useState(1)
const {
addVariantToCart,
store: { client, adding },
} = useContext(StoreContext)
const handleAddToCart = () => {
addVariantToCart(productVariant.shopifyId, quantity)
}
const text = "Add To Cart";
const [buttonText, setButtonText] = useState(text);
useEffect(() => {
const timer = setTimeout(() => {
setButtonText(text);
}, 1000);
return () => clearTimeout(timer);
}, [buttonText])
const handleClick = () => {
setButtonText("Added");
handleAddToCart();
}
return (
<>
<button
className="add"
type="submit"
disabled={!available || adding}
onClick={handleClick}
>
Add to Cart
</button>
{!available && <p>This Product is out of Stock!</p>}
</>
you need to use the buttonText inside the button as below, however, in your code you have used the hard text Add to Cart.
<button
className="add"
type="submit"
disabled={!available || adding}
onClick={handleClick}
>
{buttonText}
</button>
I'm trying to create 2 buttons in react app using material ui buttons with both buttons are enabled at the start of page load. When onClick on one of the button, the other button should be disabled vice versa.
Initial state
When onClick
const [btn1, setBtn1] = useState(false);
const [btn2, setBtn2] = useState(false);
const onBtn1 = () => {
setBtn1(!btn1);
};
const onBtn2 = () => {
setBtn2(!btn2);
};
}
How do i go about doing it? is there anyway to just use a single useState hook to handle 2 state buttons?
You can achieve this with only one state variable and one function
Code
const [disabledButton, setDisabledButton] = useState('');
const onButtonClick = (param) => {
setDisabledButton(param);
}
<Button onClick={() => onButtonClick('btn2')} disabled={disabledButton === 'btn1'}>
Button 1
</Button>
<Button onClick={() => onButtonClick('btn1')} disabled={disabledButton === 'btn2'}>
Button 2
</Button>
You can just enable the other button when a button is clicked:
const onBtn1 = () => {
setBtn1(prevState => !prevState);
setBtn2(false);
};
const onBtn2 = () => {
setBtn2(prevState => !prevState);
setBtn1(false);
};
in the JSX:
<button onClick={onBtn1} disabled={btn1}>btn1</button>
<button onClick={onBtn2} disabled={btn2}>btn2</button>
Change the state of other button on press.
const [btn1, setBtn1] = useState(true); //Initially both buttons are enabled
const [btn2, setBtn2] = useState(true);
const onBtn1 = () => {
setBtn1(!btn1);
setBtn2(false);
};
const onBtn2 = () => {
setBtn2(!btn2);
setBtn1(false);
};
}
you can use a single state, please refer the suggestion below:
state and event handlers-
const [activeButton, setActiveButton] = useState("None");
const onBtn1 = () => {
setActiveButton("Button1");
};
const onBtn2 = () => {
setActiveButton("Button2");
};
HTML Element part -
<Button disabled={!['None', 'Button1'].includes(activeButton)}>Button1</Button>
<Button disabled={!['None', 'Button2'].includes(activeButton)}>Button2</Button>