Help

Re: AMA Custom Blocks Contest Edition #3 - Releasing your block

3408 2
cancel
Showing results for 
Search instead for 
Did you mean: 
Michelle_Valent
7 - App Architect
7 - App Architect

The Custom Blocks contest deadline is approaching! Do you have questions about releasing or debugging your block? We’re hosting our third live Ask Me Anything (AMA) session in this thread on Wednesday (6/24) at 11am PT.

Billy Littlefield and Tim Deng from our platform engineering team will be ready to answer any development questions you have.

We’ll be picking 3 questions at random to win a $40 Amazon gift card. Any solutions offered by the community will be included in the draw as well. You can even start posting your questions now, and we’ll be answering questions live from 11am - 11:30am PT on Wednesday. See you there!

35 Replies 35

When invoking a custom block from a button, is there a way to tell when a button has been pressed again? I can tell if a button for a different record has been pressed because I can compare the current record with the previous record, but I would also like to be able to tell if the button for the same record has been pressed again.

Use case: the user presses the button to start a wizard, which progresses through some screens. If the user presses the button again, I would like to start the wizard over again from the beginning.

I think what Kasra was getting at is closer to your latter point – writing unit tests against stateless logic which doesn’t interact directly with the base (e.g. testing data manipulation logic that happens before sending to the base or after fetching from the base). You could use mock data and/or stubs to help seed the functions you’re testing.

Improving the testability of blocks & coming up with a more concrete guide of best practices is something we’re thinking about for the future!

Unfortunately that isn’t possible; blocks operate in an iframe with a separate context from the rest of the page. We’re thinking about other ways to provide notifications (e.g. toasts), but that isn’t something that currently exists.

Jeremy’s answer should solve this – if you store the newly created record ID in some local state, then on a future re-render the records returned from useRecords should contain the new record, and you can call expandRecord.

If you did want to fetch the new record in the same block of code, I think you could do so doing something like this:

const newRecordId = await table.createRecordAsync(...)
const freshQueryResult = await table.selectRecordsAsync()
expandRecord(freshQueryResult.getRecordById(newRecordId))

But depending on how often this gets called, it may be better to just wait for the next render cycle.

What determines how soon a new render occurs?

How do you recommend showing a <Loader scale={0.3} /> while doing a fetch?
Do I use state to keep track of when the fetch has been sent, and then change state when the response is received? Is there an easier way?

That information is set automatically, by the person who last runs block release . Like you noted, it’s tied to an Airtable account so you can’t manually edit it (but you can have a creator on your base release a version of the block to change it to their name and email).

That version isn’t exposed anywhere, but can be used internally (e.g. to supplement your commit history). When you block release, all installations of that block will reference the new code, so it isn’t possible for users to be on different versions of the same block currently. We’re thinking about ways to expose when a new release has been pushed up to the consumer!

Under the hood, versioning is still something that can be done - for example if you there are required schema changes you’d like to enforce upon a new release. One strategy you could take here is to store it version in GlobalConfig, then perform some logic that runs in your root component and can perform necessary operations if needed –

e.g.

if (globalConfig.get('blockVersion') < 2) {
    globalConfig.setPathsAsync([
        {path: 'someNewPath', value: 'default'},
        {path: 'blockVersion', value: 2}
    ])
}

This could be wrapped into a custom useBlockVersion hook or similar.

It largely depends on how the block is architected, but here are some examples –

If you’re using a standard react useState hook, a rerender will trigger anytime you modify the state using the returned setter (e.g. const [value, setValue] = useState(0) whenever setValue is called).

If you’re using the useRecords hook, a rerender will fire anytime a record is deleted / added in the base, or cell values change, or record colors change (this includes changes that propagate from the block itself). For the hooks provided by the SDK, this is determined by the watchable keys. This is a little in the weeds, but you can see which watchable keys useRecords uses here. You can even define your own triggers by using useWatchable on an Airtable model directly

Hmm, I’m not sure what might be causing this off the top of my head. This is on block init ? If this continues occurring or you’re able to reproduce more reliably, please write in to blocks@airtable.com so we can try to debug further