docs.waku.org/docs/guides/js-waku/use-waku-react.md
LordGhostX 627f7f8a8c
@waku/react docs (#90)
* add @waku/react outline

* add @waku/react hooks docs

* add @waku/react providers docs

* add more snippet comments + fix code indents
2023-07-15 22:54:13 +01:00

9.8 KiB

title
Build React DApps Using @waku/react

The @waku/react package provides components and UI adapters to integrate js-waku into React applications effortlessly. This guide provides detailed steps for using @waku/react in your project.

Install the Dependencies

First, set up a project using any production-grade React framework or use an existing React application. For this guide, we will create a boilerplate using Create React App (CRA):

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
npx create-react-app [PROJECT DIRECTORY]
yarn create react-app [PROJECT DIRECTORY]

Next, install the @waku/react package using your preferred package manager:

npm install @waku/react @waku/sdk
yarn add @waku/react @waku/sdk

Create a Relay Node

Use the useCreateRelayNode() hook to create a Relay Node:

import { useCreateRelayNode } from "@waku/react";

function App() {
	// Create and start a Relay Node
	const { node, error, isLoading } = useCreateRelayNode({
		options: {
			defaultBootstrap: true,
			emitSelf: true,
		}
	});

	// "node" is the created Relay Node
	// "error" captures any error that occurs during node creation
	// "isLoading" indicates whether the node is still being created
	// Use these to handle states and render the UI in your application
}

Create a Light Node

Use the useCreateLightNode() hook to create a Light Node and specify the protocols for remote peers:

import { useCreateLightNode } from "@waku/react";
import { Protocols } from "@waku/interfaces";

function App() {
	// Create and start a Light Node and wait for remote peers
	const { node, error, isLoading } = useCreateLightNode({
		options: { defaultBootstrap: true },
		protocols: [Protocols.LightPush, Protocols.Filter],
	});

	// "node" is the created Light Node
	// "error" captures any error that occurs during node creation
	// "isLoading" indicates whether the node is still being created
	// Use these to handle states and render the UI in your application
}

Create an Encoder and Decoder

Use the useCreateContentPair() hook to create a message encoder and decoder pair:

import { useCreateContentPair } from "@waku/react";

function App() {
	// Choose a content topic
	const contentTopic = "/waku-react-guide/1/message/utf8";
	const ephemeral = false;

	// Create a message encoder and decoder pair
	const { encoder, decoder } = useCreateContentPair(contentTopic, ephemeral);

	// "encoder" is the message encoder
	// "decoder" is the message decoder
	// Use these to handle the messages in your application
}

Send Messages Using Light Push

Use the useLightPush() hook to bind Light Push methods to a node and encoder:

import {
	useCreateLightNode,
	useCreateContentPair,
	useLightPush,
} from "@waku/react";
import { Protocols } from "@waku/interfaces";
import { utf8ToBytes } from "@waku/sdk";

function App() {
	// Create and start a Light Node and wait for remote peers
	const { node, error, isLoading } = useCreateLightNode({
		options: { defaultBootstrap: true },
		protocols: [Protocols.LightPush, Protocols.Filter],
	});

	// Choose a content topic and create an encoder
	const contentTopic = "/waku-react-guide/1/message/utf8";
	const { encoder  } = useCreateContentPair(contentTopic);

	// Wait for the node to finish loading before sending messages
	// (isLoading === false)

	// Bind push method to a node and encoder
	const { push } = useLightPush({ node, encoder });

	// Send the message using Light Push
	const sendMessage = async (text) => {
		if (!push || !text) {
			return;
		}
		const payload = utf8ToBytes(text);
		await push({ payload });
	};
	sendMessage("Hello, World!");
}

:::info Wait for the node to finish loading before sending messages (isLoading === false). :::

Receive Messages Using Filter

Use the useFilterMessages() hook to receive messages from a Filter subscription:

import {
	useCreateLightNode,
	useCreateContentPair,
	useFilterMessages,
} from "@waku/react";
import { Protocols } from "@waku/interfaces";

function App() {
	// Create and start a Light Node and wait for remote peers
	const { node } = useCreateLightNode({
		options: { defaultBootstrap: true },
		protocols: [Protocols.LightPush, Protocols.Filter],
	});

	// Choose a content topic and create a decoder
	const contentTopic = "/waku-react-guide/1/message/utf8";
	const { decoder } = useCreateContentPair(contentTopic);

	// Receive messages from Filter subscription
	const { error, messages, isLoading } = useFilterMessages({ node, decoder });
	console.log(messages);

	// "error" captures any error that occurs while receiving messages
	// "messages" contains a list of messages the subscription received
	// "isLoading" indicates whether the node is still subscribing to Filter
	// Use these to handle states and render the UI in your application
}

Retrieve Messages Using Store

Use the useStoreMessages() hook to retrieve messages from the Store protocol:

import {
	useCreateLightNode,
	useCreateContentPair,
	useStoreMessages,
} from "@waku/react";
import { Protocols, PageDirection } from "@waku/interfaces";

function App() {
	// Create and start a Light Node and wait for remote peers
	const { node } = useCreateLightNode({
		options: { defaultBootstrap: true },
		protocols: [Protocols.LightPush, Protocols.Filter],
	});

	// Choose a content topic and create a decoder
	const contentTopic = "/waku-react-guide/1/message/utf8";
	const { decoder } = useCreateContentPair(contentTopic);

	// Set the query options
	const options = {
		pageDirection: PageDirection.BACKWARD,
		pageSize: 20,
	};

	// Query the Store peer
	const { error, messages, isLoading } = useStoreMessages({ node, decoder, options });
	console.log(messages);

	// "error" captures any error that occurs during message retrieval
	// "messages" contains a list of messages retrieved from the Store peer
	// "isLoading" indicates whether the node is still retrieving messages
	// Use these to handle states and render the UI in your application
}

:::info To explore the available query options, please refer to the Store Query Options guide. :::

Using @waku/react Providers

The @waku/react package provides a collection of context providers to pass configuration options throughout the component hierarchy:

RelayNodeProvider

The RelayNodeProvider context provider passes configuration options for creating a Relay Node:

import { RelayNodeProvider } from "@waku/react";
import { Protocols } from "@waku/interfaces";

// Set the Relay Node options
const NODE_OPTIONS = {
	defaultBootstrap: true,
	emitSelf: true,
};

// Set the remote peer connections to wait for
const PROTOCOLS = [Protocols.Relay];

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
	<React.StrictMode>
		// Use the Relay Node context provider
		<RelayNodeProvider options={NODE_OPTIONS} protocols={PROTOCOLS}>
			<App />
		</RelayNodeProvider>
	</React.StrictMode>
);
import { useWaku } from "@waku/react";

function App() {
	// Create and start a Relay Node
	const { node, error, isLoading } = useWaku();
	// Use these to handle states and render the UI in your application
}

LightNodeProvider

The LightNodeProvider context provider passes configuration options for creating a Light Node:

import { LightNodeProvider } from "@waku/react";
import { Protocols } from "@waku/interfaces";

// Set the Light Node options
const NODE_OPTIONS = { defaultBootstrap: true };

// Set the remote peer connections to wait for
const PROTOCOLS = [
	Protocols.LightPush,
	Protocols.Filter,
];

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
	<React.StrictMode>
		// Use the Light Node context provider
		<LightNodeProvider options={NODE_OPTIONS} protocols={PROTOCOLS}>
			<App />
		</LightNodeProvider>
	</React.StrictMode>
);
import { useWaku } from "@waku/react";

function App() {
	// Create and start a Light Node
	const { node, error, isLoading } = useWaku();
	// Use these to handle states and render the UI in your application
}

ContentPairProvider

The ContentPairProvider context provider passes configuration options for creating an encoder and decoder pair:

import { ContentPairProvider } from "@waku/react";

// Choose a content topic
const CONTENT_TOPIC = "/waku-react-guide/1/message/utf8";
const EPHEMERAL = false;

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
	<React.StrictMode>
		// Use the content pair context provider
		<ContentPairProvider contentTopic={CONTENT_TOPIC} ephemeral={EPHEMERAL}>
			<App />
		</ContentPairProvider>
	</React.StrictMode>
);
import { useContentPair } from "@waku/react";

function App() {
	// Create a message encoder and decoder pair
	const { encoder, decoder } = useContentPair();
	// Use these to handle the messages in your application
}

:::tip You have successfully integrated js-waku into a React application using the @waku/react package. Check out the web-chat example for a working demo. :::