React
React is a popular library for building declarative, component-based UI.
Electric and React
Electric has first-class support for React. We maintain a react-hooks package that provides a number of React Hooks to bind Shape data to your components.
How to use
Install
The package is published on NPM as @electric-sql/react
. Install using e.g.:
npm i @electric-sql/react
useShape
useShape
binds a materialised Shape to a state variable. For example:
import { useShape } from '@electric-sql/react'
const MyComponent = () => {
const { isLoading, data } = useShape<{title: string}>({
url: `http://localhost:3000/v1/shape`,
params: {
table: 'items'
}
})
if (isLoading) {
return <div>Loading ...</div>
}
return (
<div>
{data.map(item => <div>{item.title}</div>)}
</div>
)
}
You can also include additional PostgreSQL-specific parameters:
const MyFilteredComponent = () => {
const { isLoading, data } = useShape<{id: number, title: string}>({
url: `http://localhost:3000/v1/shape`,
params: {
table: 'items',
where: 'status = \'active\'',
columns: ['id', 'title']
}
})
// ...
}
useShape
takes the same options as ShapeStream. The return value is a UseShapeResult
:
export interface UseShapeResult<T extends Row<unknown> = Row> {
/**
* The array of rows that make up the materialised Shape.
* @type {T[]}
*/
data: T[]
/**
* The Shape instance used by this useShape
* @type {Shape<T>}
*/
shape: Shape<T>
/** True during initial fetch. False afterwise. */
isLoading: boolean
/** Unix time at which we last synced. Undefined when `isLoading` is true. */
lastSyncedAt?: number
/** Unix time at which we last synced. Undefined when `isLoading` is true. */
isError: boolean
error: Shape<T>[`error`]
}
preloadShape
preloadShape
is useful to call in route loading functions or elsewhere when you want to ensure Shape data is loaded before rendering a route or component.
export const clientLoader = async () => {
return await preloadShape({
url: `http://localhost:3000/v1/shape`,
params: {
table: 'items'
}
})
}
You can also preload filtered data:
export const filteredLoader = async () => {
return await preloadShape({
url: `http://localhost:3000/v1/shape`,
params: {
table: 'items',
where: 'category = \'electronics\'',
columns: ['id', 'name', 'price']
}
})
}
It takes the same options as ShapeStream.
getShapeStream
getShapeStream<T>
get-or-creates a ShapeStream
off the global cache.
const itemsStream = getShapeStream<Item>({
url: `http://localhost:3000/v1/shape`,
params: {
table: 'items'
}
})
This allows you to avoid consuming multiple streams for the same shape log.
getShape
getShape<T>
get-or-creates a Shape
off the global cache.
const itemsShape = getShape<Item>({
url: `http://localhost:3000/v1/shape`,
params: {
table: 'items'
}
})
This allows you to avoid materialising multiple shapes for the same stream.