admin管理员组

文章数量:1303536

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>;

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>;
Share Improve this question asked Feb 10, 2021 at 10:13 JAGENI NatJAGENI Nat 254 bronze badges 1
  • 1 onclick={fetchingId(attributes.id)} - did you forget the () => as in onclick={() => fetchingId(attributes.id)} ? Because you should actually pass a function and not the result of a function call. Otherwise, that would result in the fetchingId() being called everytime the component is rendered.. See this FAQ on the React website, but that "pass a function" is not just in React - even in native JS, that's indeed how it works. – Sally CJ Commented Feb 10, 2021 at 13:12
Add a comment  | 

1 Answer 1

Reset to default 2

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

本文标签: woocommerce offtopicHow to stop a Gutenberg Block from firing multiple GET Requests