I’ve been building a Gutenberg Block that sends a GET request to the Woocommerce REST API.
It is composed of a text input that receives an ID of a product and fetches it to the Woocommerce REST API. It also has a button that fires a function to fetch the product with the API.
The issue with the GET Requests
The fetching works well, but it keeps sending multiple GET requests, even when I do not click the button to fire the function. Simply clicking the input sends multiple requests when I only need one everytime I change the ID and click the button.
I’m importing WooCommerceRestApi from "@woocommerce/woocommerce-rest-api" and use Node.js.
The code
This is the first part of the edit function:
const edit = ({ attributes, setAttributes }) => {
const blockProps = useBlockProps();
// Wrapped the WooCommerce.get() function in a function named `fetchingId` to call it with a button
const fetchingId = async (id) => {
// The WooCoommerce.get() function
const response = await WooCommerce.get(`products/${id}`)
.then((response) => {
console.log(response.data);
setAttributes({ price: response.data.price });
setAttributes({ name: response.data.name });
})
.catch((error) => {
console.log(error.response.data);
setAttributes({ price: '' });
setAttributes({ name: '' });
});
}
...
}
This is another part of the function: an input that updates the Product ID that is used for the GET request and a button linked to the fetchingId() function.
return <div {...blockProps}>
<div class="wrapper-input" >
<TextControl
label={__('ID du Produit', 'ingredient-unique')}
value={attributes.id}
onChange={(val) => setAttributes({ id: val })}
className='control-id'
/>
</div>
<button onclick={fetchingId(attributes.id)}>Chercher le produit</button>
...
</div>;
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
You’re not supposed to make HTTP requests etc directly inside React components, you need to use useEffect.
A react component needs to run as quickly as possible, even if work that needs doing isn’t finished yet. By using useEffect you tell React to run a separate function after rendering is complete, giving you the opportunity to make requests and for your component to have “effects”. React also lets you pass a list of dependencies that it will watch, and if they change the effect re-runs.
What you have however, is a side effect that runs directly in the component. As a result, whenever the component is re-rendered, your code makes a HTTP fetch, which aside from this problem is also going to significantly slow down the editor. A re-render could happen at any time by design. A window resize, stray dom event, state changes in parent components, etc
If it helps, a common way to show this is with something like this:
const { isLoading, setLoading } = useState( false );
This way you can call setLoading( false ) at the end of your useEffect function, and then display a loading message in the component
This is another part of the function: an input that updates the Product ID that is used for the GET request and a button linked to the fetchingId() function.
You cannot rely on those values being present here. You can trigger a function via an event, and that function can have side effects such as HTTP requests, but you can’t do those things directly in the component. Rendering the component should render the component, and only render the component, everything else goes in lifecycle hooks/functions
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0