Crear un frontend para tu dapp usando React
Esta sección explica cómo los frontends de tu dapp pueden interactuar con los contratos de ejemplo y acceder a datos de la cadena, además de conectarse a una billetera freighter. Esto se ilustrará utilizando bibliotecas proporcionadas por @soroban-react
, un marco simple y poderoso para desarrollar Dapps modernas usando React. @soroban-react
fue creada y es mantenida por un increíble miembro de la comunidad!
Esta guía demostrará cómo se desarrolló un frontend de un dapp de crowdfunding de ejemplo con React. Aunque gran parte del código es específico para este proyecto, los principios demostrados deberían ser lo suficientemente educativos para ayudarte a comenzar.
A continuación se muestra una lista de las bibliotecas utilizadas a lo largo del código del frontend y sus respectivas importaciones:
import { SorobanReactProvider } from "@soroban-react/core";
import { testnet, sandbox, standalone } from "@soroban-react/chains";
import { freighter } from "@soroban-react/freighter";
import { ChainMetadata, Connector } from "@soroban-react/types";
import type {
WalletChain,
ChainMetadata,
ChainName,
} from "@soroban-react/types";
import { useSorobanReact } from "@soroban-react/core";
Estas importaciones incluyen SorobanReactProvider
de @soroban-react/core
, que es un proveedor de contexto utilizado para pasar la instancia de SorobanReact a otros componentes. También importas varios tipos como WalletChain
, ChainMetadata
y ChainName
, que ayudan a mantener la seguridad de tipos dentro de nuestra aplicación.
Componentes de React y Pasaje de Props
React prospera en su arquitectura basada en componentes. Los componentes son piezas reutilizables de código que devuelven un elemento de React para ser renderizado en la página. Una aplicación típica de React consiste en múltiples componentes que trabajan en armonía para crear una interfaz de usuario dinámica.
Miremos un componente del dapp de crowdfunding de ejemplo, el componente MintButton
:
function MintButton({
account,
decimals,
symbol,
}: {
account: string;
decimals: number;
symbol: string;
}) {
const [isSubmitting, setSubmitting] = useState(false);
const { activeChain, server } = useNetwork();
const networkPassphrase = activeChain?.networkPassphrase ?? "";
const { sendTransaction } = useSendTransaction();
const amount = BigNumber(100);
return <Button props omitted here />;
}
Este componente funcional toma tres propiedades como argumentos: account
, decimals
y symbol
. Demuestra el concepto de paso de props, una forma de pasar datos de componentes padre a hijo en React. La prop onComplete
incluso te permite pasar funciones a tus componentes como props. También vemos el hook useState
de React para la gestión del estado local, un método para preservar valores entre llamadas a funciones.
Gestión del Estado y Hooks
La gestión del estado es otro concepto central de React, permitiendo que los componentes creen y manejen sus propios datos. El useState
hook es una característica introducida en React 16.8 que permite a los componentes funcionales tener su propio estado.
En el componente MintButton
, el hook useState
se utiliza para gestionar el estado isSubmitting
:
const [isSubmitting, setSubmitting] = useState(false);
El hook useState
devuelve un par de valores: el estado actual y una función que lo actualiza. En este caso, el estado isSubmitting
se inicializa en false
y la función setSubmitting
se utiliza para actualizarlo. React también permite la creación de hooks personalizados, como useNetwork
y useSendTransaction
, para encapsular y reutilizar lógica con estado en múltiples componentes.
Hooks Personalizados
Los hooks de React son funciones que te permiten “conectar” con el estado de React y las características del ciclo de vida desde componentes funcionales. Los hooks personalizados te permiten encapsular lógica compleja y hacerla reutilizable en componentes. Miremos a useNetwork
y useSendTransaction
, dos hooks personalizados utilizados en el dapp de crowdfunding de ejemplo.
El hook useNetwork
se utiliza para interactuar con la red de blockchain, y el hook useSendTransaction
se usa para despachar transacciones. Estos hooks abstraen lógica compleja, facilitando la lectura y comprensión del código principal del componente.
Así es como usas estos hooks en el componente MintButton
:
const { activeChain, server } = useNetwork();
const networkPassphrase = activeChain?.networkPassphrase ?? "";
const { sendTransaction } = useSendTransaction();
useNetwork
proporciona la cadena activa y el servidor, y useSendTransaction
nos da el método sendTransaction
, que usarás más tarde para acuñar tokens. De esta manera, puedes mantener el componente enfocado en la renderización y la lógica de manejo de eventos, facilitando su prueba y mantenimiento.
Procesamiento Asincrónico y Manejo Robusto de Errores
Al tratar con operaciones que pueden tomar un tiempo impredecible, como peticiones de red o, en nuestro caso, acuñar tokens en la blockchain, el soporte de React para operaciones asincrónicas es crucial. Esto permite la ejecución del resto del código sin ser bloqueado por estas operaciones.
Adentrémonos en el fragmento de código que maneja el proceso de acuñación asincrónica:
try {
console.log("Minting the token...");
const paymentResult = await sendTransaction(
new SorobanClient.TransactionBuilder(adminSource, {
networkPassphrase,
fee: "1000",
})
.setTimeout(10)
.addOperation(
SorobanClient.Operation.payment({
destination: walletSource.accountId(),
asset: new SorobanClient.Asset(symbol, Constants.TokenAdmin),
amount: amount.toString(),
}),
)
.build(),
{
timeout: 10 * 1000,
skipAddingFootprint: true,
secretKey: Constants.TokenAdminSecretKey,
sorobanContext,
},
);
console.debug(paymentResult);
sorobanContext.connect();
} catch (err) {
console.log("Error while minting the token: ", err);
console.error(err);
}
Este bloque es donde ocurre la acuñación real de tokens. Está envuelto en un bloque try-catch
, asegurando que cualquier error durante el proceso de acuñación sea capturado y manejado adecuadamente, evitando que la aplicación se bloquee y dándote la oportunidad de proporcionar retroalimentación al usuario.
La palabra clave await
pausa la ejecución de la función hasta que la promesa devuelta por sendTransaction
se resuelva. sendTransaction
es una función obtenida de nuestro hook useSendTransaction
, y construye y envía una operación de pago a la red Stellar.
El método sendTransaction
acepta dos argumentos: una instancia de TransactionBuilder
y un objeto de opciones. El TransactionBuilder
establece los detalles de la transacción, como la cuenta de origen, la frase de red, la tasa de transacción y las operaciones a realizar—en este caso, una operación de pago.
Si la transacción tiene éxito, paymentResult
contiene el resultado, que registras para fines de depuración. Si ocurre un error durante la transacción, la función lanza un error, el cual capturas y registras.
Conclusión
React ofrece una variedad de conceptos de alto nivel que pueden mejorar drásticamente tu proceso de desarrollo web. Al comprender y utilizar estos conceptos—como componentes, paso de props, gestión de estado, operaciones asincrónicas y manejo de errores—puedes crear aplicaciones escalables, mantenibles y eficientes.
Recuerda, la clave para dominar React es la práctica. ¡Así que sigue construyendo y experimentando!
Guías en esta categoría:
📄️ Usar Docker para crear y ejecutar dapps
Entender Docker y usarlo para crear aplicaciones
📄️ Guía completa de frontend para dapps Stellar
Aprende a crear interfaces de frontend funcionales para dapps Stellar usando React, Tailwind CSS y el Stellar SDK.
📄️ Inicializa una dapp usando scripts
Configura la inicialización correctamente para asegurar un proceso fluido para tu dapp
📄️ Crear un frontend para tu dapp usando React
Conectar frontends de dapp a contratos y la billetera Freighter usando @soroban-react
📄️ Desarrollar plantillas de interfaz de usuario para la inicialización de contratos
Entender, encontrar y crear tus propias plantillas de interfaz de usuario para usarlas con el comando `stellar contract init` de Stellar CLI
📄️ Implementar archivo de estado en dapps
Aprender cómo implementar archivo de estado en tu dapp
📄️ Trabajar con especificaciones de contrato en Java, Python y PHP
Una guía para entender e interactuar con los contratos inteligentes de Soroban en diferentes lenguajes de programación