# React

### UseEffect

{% embed url="<https://reactjs.org/docs/hooks-effect.html>" %}

### ReactNodes

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

{% code title="gravity/frontend/components/blocks/promotions/PromotionsBlock.tsx" %}

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

{% endcode %}

Here we add the `editorControls` to the backend render.

{% code title="gravity/backend/plugins/gravity-platform-core/src/blocks/promotions/edit.tsx" %}

```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>
		)}
	</>
}
```

{% endcode %}

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.

![](/files/5JOcxJ8yeP8jfVdJzpGv)

### Converting Ids to Actual Objects

{% code title="frontend/components/blocks/promotions/PromotionsBlock.tsx" %}

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

{% endcode %}

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://shaunh.gitbook.io/kairos/react.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
