skip to Main Content

I am using Airtable blocks to create an extension. I have a button that, when pressed, should retrieve the records. However, I am not able to get it to run when the button is clicked…only when the button is loaded. I only want it to run when clicked since I have a lot of tables and loading all the records from all the tables at once could be overkill. How do I get it to run only when I press the button? The error I get is Error: Invalid hook call. Hooks can only be called inside of the body of a function component. Without the

 import React, { useState, useEffect } from "react";
 import { useBase, useRecords, Button } from "@airtable/blocks/ui";
 
 function getRecords(Item) {
   const base = useBase();
   const table = base.getTableIfExists(Item.table);
   return useRecords(table);
 }
 
 export default function RunButton({ Item }) {
   // This works but will potentially load a LOT of data
   const records = getRecords(Item);
   records.map((record) => {
     console.log(record.id);
   });
 
   // This errors
   function onClick() {
     const records = getRecords(Item);
     records.map((record) => {
       console.log(record.id);
     });
   }
 
   return (
     <Button size="small" icon="play" onClick={onClick}>
       Run
     </Button>
   );
 }

2

Answers


  1. useBase and useRecords seems like are custom hooks (which may include native React hooks). You mustn’t call a hook conditionally, such as in a event/callback function.

    Try removing

    const records = getRecords(Item);
    

    from the onClick function. The content of records should update automatically when Item is changed. You don’t need to call it the second time.

    import React, { useState, useEffect } from "react";
    import { useBase, useRecords, Button } from "@airtable/blocks/ui";
    
    function getRecords(Item) {
      const base = useBase();
      const table = base.getTableIfExists(Item.table);
      return useRecords(table);
    }
    
    export default function RunButton({ Item }) {
      const records = getRecords(Item);
      records.map((record) => {
        console.log(record.id);
      });
    
      function onClick() {
        // remove this line, everything should work the same
        // const records = getRecords(Item);
        records.map((record) => {
          console.log(record.id);
        });
      }
    
      return (
        <Button size="small" icon="play" onClick={onClick}>
          Run
        </Button>
      );
    }
    
    Login or Signup to reply.
  2. The error occurs because hooks like useBase and useRecords can only be called at top level of function component not inside other function or event handlers like onClick.You should call then at top of your RunButton component and use like this:

    const base = useBase();
      const table = base.getTableIfExists(Item.table);
    
      async function onClick() {
        const records = await table.selectRecordsAsync();
        records.records.map(record => {
          console.log(record.id);
        });
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search