React

UseEffect

ReactNodes

You can add components as props to work them into the layout of another component. Here is an example from the project.

gravity/frontend/components/blocks/promotions/PromotionsBlock.tsx
{/* BACKEND RENDER */}
{isEditing && (
	<div className="flex flex-wrap mb-12">
		{promotionsList?.map((promotion) => (
			...
		))}
		{editorControls}
	</div>
)}

Here we add the editorControls to the backend render.

gravity/backend/plugins/gravity-platform-core/src/blocks/promotions/edit.tsx
editorControls={
	<>
		{availablePromotions?.length > 0 && (
			<Listbox value={selected} onChange={setSelected}>
				<div className="relative mt-5 lg:w-1/4">
					<Listbox.Button className="relative w-full py-2 pl-3 pr-10 text-left bg-white rounded-lg shadow-md cursor-default focus:outline-none focus-visible:ring-2 focus-visible:ring-opacity-75 focus-visible:ring-white focus-visible:ring-offset-orange-300 focus-visible:ring-offset-2 focus-visible:border-indigo-500 sm:text-sm">
						<span className="block truncate">Add Promotion</span>
						<span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
							<HiOutlinePlusCircle
								className="w-5 h-5 text-gray-400"
								aria-hidden="true"
							/>
						</span>
					</Listbox.Button>
					<Transition
						as={Fragment}
						leave="transition ease-in duration-100"
						leaveFrom="opacity-100"
						leaveTo="opacity-0"
					>
						<Listbox.Options className="absolute w-full py-1 mt-1 overflow-auto text-base bg-white rounded-md shadow-lg max-h-60 ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
							{availablePromotions?.map((promo) => (
								<Listbox.Option
									key={promo.id}
									className={({ active }) =>
										`${
											active
												? "text-amber-900 bg-amber-100"
												: "text-gray-900"
										}
                              cursor-default select-none relative py-2 pl-3 pr-4`
									}
									value={promo.id}
								>
									{({ selected }) => (
										<>
											<span
												className={`${
													selected ? "font-medium" : "font-bold"
												} block truncate`}
											>
												{promo.title.rendered}
											</span>
										</>
									)}
								</Listbox.Option>
							))}
						</Listbox.Options>
					</Transition>
				</div>
			</Listbox>
		)}
	</>
}

We can pass this whole component and it's render logic as a prop. This allows us to fit it into the layout of the display component.

Converting Ids to Actual Objects

frontend/components/blocks/promotions/PromotionsBlock.tsx
const promotionsList = (
	selectedPromotionIds?.length
		? selectedPromotionIds
				?.map((id) =>
					promotions.find((promotion) => promotion.databaseId === id)
				)
				.filter((p) => p)
		: promotions
) as IPromotion[];

Here we map the IDs to the objects they represent. The final filter is to be sure that none of those are null.

Last updated

Was this helpful?