Skip to main content

React Hooks

React Hooks

The @gear-js/react-hooks library provides React hook abstractions over sails-js and its generated program library. This significantly simplifies the development of front-end applications built with Sails.

TanStack Query is used as the async state manager to handle queries and mutations, making it easier to manage asynchronous operations like fetching data (queries) and performing create/update/delete operations (mutations) against the defined program library. Therefore, most hooks' parameters and return values correspond to the library's conventions.

Hooks

useSails

The useSails hook returns a Sails instance as described in the Library Overview section, based on the provided programId and IDL description of the deployed application.

Example:

import { useSails } from '@gear-js/react-hooks';

const programId = '0x...';
const idl = '...';

const { data } = useSails({
programId,
idl,
});

console.log(data);

useProgram

The useProgram hook returns a Program instance as described in the Client Generation section using a generated library (lib.ts) and the id of a deployed application.

Example:

import { useProgram } from '@gear-js/react-hooks';
import { Program } from './lib';

const { data } = useProgram({
library: Program,
id: '0x...',
});

console.log(data);

useSendProgramTransaction

The useSendProgramTransaction hook is used to call a function (also referred to as a command in Sails) of a Sails service from the application deployed at id. It returns a mutation to sign and send a transaction for this purpose.

Note: The returned mutation callback is essentially a wrapper over the TransactionBuilder in sails-js and its signAndSend method, which will be called upon mutation execution. The useSendProgramTransaction hook abstracts this process by internally specifying an account and a @gear-js/api instance, making it a shortcut for this procedure.

Example:

import { useProgram, useSendProgramTransaction } from '@gear-js/react-hooks';
import { Program } from './lib';

function SendTransaction() {
const { data: program } = useProgram({
library: Program,
id: '0x...',
});

const { sendTransactionAsync } = useSendProgramTransaction({
program,
serviceName: 'service',
functionName: 'function',
});

const handleClick = async () => {
const result = await sendTransactionAsync({
args: ['arg', 'anotherArg'],
account: { addressOrPair: '0x...' }, // Defaults to the connected account from the extension if not provided
value: 1000000n, // Defaults to 0 if not provided
gasLimit: 1000000000n, // Automatically calculated if not provided
voucherId: '0x...', // If not provided, the transaction will be sent without a voucher
});

const response = await result.response;
console.log('response: ', response);
};

return (
<button type="button" onClick={handleClick}>
Send Transaction
</button>
);
}

export { SendTransaction };

useProgramQuery

The useProgramQuery hook is used to call a query of a Sails service from the application deployed at id. It returns a query containing the program's current state.

Example:

import { useProgram, useProgramQuery } from '@gear-js/react-hooks';
import { Program } from './lib';

function State() {
const { data: program } = useProgram({
library: Program,
id: '0x...',
});

const { data } = useProgramQuery({
program,
serviceName: 'service',
functionName: 'query',
args: ['arg', 'anotherArg'],
watch: false, // If true, initializes a subscription to the program's state changes in the Gear MessagesDispatched event. Can increase network traffic.
});

return <div>{JSON.stringify(data)}</div>;
}

useProgramEvent

The useProgramEvent hook initializes a subscription to a specified program event.

Example:

The useProgramEvent hook below sets up a listener on the event function of the specified service and executes the onData callback with the new data whenever the event is triggered.

import { useProgram, useProgramEvent } from '@gear-js/react-hooks';
import { Routing } from './pages';
import { Program } from './lib';

function App() {
const { data: program } = useProgram({
library: Program,
id: '0x...',
});

useProgramEvent({
program,
serviceName: 'service',
functionName: 'event',
onData: (data) => console.log(data),
});

return (
<main>
<Routing />
</main>
);
}

export { App };

Prepare Hooks

When performing long-running asynchronous work in response to a user transaction using useSendProgramTransaction) hook, the user only receives feedback on the transaction status after transaction is complete. Prepare hooks can be used to eagerly obtain values before user interaction or to perform upfront validation before sending a transaction.

usePrepareProgramTransaction

The usePrepareProgramTransaction hook returns a mutation that retrieves the intermediate transaction state for a specified function and service of a deployed application at id.

This hook is useful for eagerly obtaining values such as gasLimit, extrinsic, and transactionFee, which are essential for providing a smoother user experience.

Example:

The example below shows how to obtain the transactionFee for a transaction, which can be used to validate or display the fee to the user before proceeding.

import { useProgram, usePrepareProgramTransaction } from '@gear-js/react-hooks';
import { Program } from './lib';

function LogTransactionFeeButton() {
const { data: program } = useProgram({
library: Program,
id: '0x...',
});

const { data, prepareTransactionAsync } = usePrepareProgramTransaction({
program,
serviceName: 'service',
functionName: 'function',
});

const handleClick = async () => {
const transaction = await prepareTransactionAsync({
args: ['arg', 'anotherArg'],
account: { addressOrPair: '0x...' },
value: 1000000n,
gasLimit: 1000000000n,
voucherId: '0x...',
});

const fee = await transaction.transactionFee();
console.log('fee: ', fee);
};

return (
<button type="button" onClick={handleClick}>
Log Transaction Fee
</button>
);
}

export { LogTransactionFeeButton };

Example:

Using the hook in combination with useSendProgramTransaction:

import { useProgram, usePrepareProgramTransaction, useSendProgramTransaction } from '@gear-js/react-hooks';
import { Program } from './lib';

function SendPreparedTransaction() {
const { data: program } = useProgram({
library: Program,
id: '0x...',
});

const { prepareTransactionAsync } = usePrepareProgramTransaction({
program,
serviceName: 'service',
functionName: 'function',
});

const { sendTransactionAsync } = useSendProgramTransaction({
program,
serviceName: 'service',
functionName: 'function',
});

const handleClick = async () => {
const transaction = await prepareTransactionAsync({
args: ['arg', 'anotherArg'],
account: { addressOrPair: '0x...' },
value: 1000000n,
gasLimit: 1000000000n,
voucherId: '0x...',
});

const fee = await transaction.transactionFee();
console.log('fee: ', fee);

const result = await sendTransactionAsync(transaction);
const response = await result.response;

console.log('response: ', response);
};

return (
<button type="button" onClick={handleClick}>
Prepare and Send Transaction
</button>
);
}

export { SendPreparedTransaction };