Skip to main content

Interactive bricks with RSC

When using the react-bricks/rsc library in a Server Components starter, if you have interactive bricks, which need client hydration, you need to create 2 components: a server wrapper and the client component, in this way:

Map.tsx
import { types, wrapClientComponent } from 'react-bricks/rsc'
import { RegisterComponent } from 'react-bricks/rsc/client'

import MapClient, { MapProps } from './MapClient'

const MAPTILER_ACCESS_TOKEN = '' // Insert access token

const schema: types.IBlockType<MapProps> = {
name: 'map',
label: 'Map',
category: 'contact',
tags: ['contacts', 'map'],
playgroundLinkLabel: 'View source code on Github',
playgroundLinkUrl:
'https://github.com/ReactBricks/react-bricks-ui/blob/master/src/website/Map/Map.tsx',
previewImageUrl: `/bricks-preview-images/map.png`,
getDefaultProps: () => ({
lat: '45.6782509',
lng: '9.5669407',
zoom: '6',
}),
sideEditProps: [
{
name: 'zoom',
label: 'Zoom',
type: types.SideEditPropType.Number,
},
{
name: 'lat',
label: 'Latitude',
type: types.SideEditPropType.Number,
},
{
name: 'lng',
label: 'Longitude',
type: types.SideEditPropType.Number,
},
{
name: 'maptiler',
label: 'MapTiler',
type: types.SideEditPropType.Custom,
show: () => !MAPTILER_ACCESS_TOKEN,
component: () => {
if (!MAPTILER_ACCESS_TOKEN) {
return (
<p className="text-sm">
For better maps, please create a MapTiler free account and set the{' '}
<code className="text-xs">MAPTILER_ACCESS_TOKEN</code> string.
</p>
)
}
return null
},
},
],
}

export default wrapClientComponent({
ClientComponent: MapClient,
RegisterComponent,
schema,
})
MapClient.tsx
'use client'

import { Map, Marker } from 'pigeon-maps'
import { maptiler } from 'pigeon-maps/providers'
import React from 'react'

export interface MapProps {
zoom: string
lat: string
lng: string
mapTilerAccessToken: string
}

export const MapClient: React.FC<MapProps> = ({
lat = '45.6782509',
lng = '9.5669407',
zoom = '10',
mapTilerAccessToken,
}) => {
const mapTilerProvider = React.useCallback(
(x: number, y: number, z: number, dpr?: number | undefined) =>
maptiler(mapTilerAccessToken, 'streets')(x, y, z, dpr),
[mapTilerAccessToken]
)

let mapTilerProviderProp = {}

if (mapTilerAccessToken) {
mapTilerProviderProp = {
provider: mapTilerProvider,
}
}

return (
<Map
center={[parseFloat(lat), parseFloat(lng)]}
height={350}
metaWheelZoom
zoom={parseInt(zoom, 10)}
{...mapTilerProviderProp}
dprs={[1, 2]}
metaWheelZoomWarning="Use ctrl + wheel to zoom!"
attribution={false}
>
<Marker anchor={[parseFloat(lat), parseFloat(lng)]} />
</Map>
)
}

export default MapClient