Hello Builder.io Support Team,
I am experiencing an issue with a custom React component integrated into Builder.io. The component consists of a search bar and an accordion list. However, when I bind data to the component in Builder.io, the search bar repeats for each item in the list instead of appearing just once at the top.
Here are the details:
Component Structure:
- Search Component (Search.jsx): Handles search input and filters items based on the search term.
- Accordion List Component (AccordionList.jsx): Renders a list of items passed as props.
- Parent Component (AccordionWithSearch.jsx): Manages the state, renders the Search component and the AccordionList component, and passes the necessary props.
// search component
import React, { useState } from 'react';
import { TextField } from '@mui/material';
const Search = ({ onFilter }) => {
const [searchTerm, setSearchTerm] = useState('');
const handleSearch = (event) => {
const value = event.target.value.toLowerCase();
setSearchTerm(value);
onFilter(value);
};
return (
<div className="search-container">
<TextField
label="Search"
variant="outlined"
fullWidth
margin="normal"
value={searchTerm}
onChange={handleSearch}
/>
</div>
);
};
export default Search;
AccordionList.jsx
:
import React from 'react';
import { Accordion, AccordionSummary, AccordionDetails, Typography } from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
const AccordionList = ({ items }) => {
return (
<div className="bg-white p-5">
{items.length > 0 ? (
items.map((item, index) => (
<Accordion key={index}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography>{item.title}</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>{item.content}</Typography>
</AccordionDetails>
</Accordion>
))
) : (
<Typography variant="h6">No Items Found</Typography>
)}
</div>
);
};
export default AccordionList;
AccordionWithSearch.jsx
import React, { useState, useEffect } from 'react';
import { Builder } from '@builder.io/react';
import Search from './Search';
import AccordionList from './AccordionList';
const AccordionWithSearch = ({ items = [] }) => {
const [filteredItems, setFilteredItems] = useState(items);
useEffect(() => {
console.log('Initial items:', items);
}, [items]);
const handleFilter = (searchTerm) => {
console.log('Search term:', searchTerm);
const newFilteredItems = searchTerm
? items.filter(item =>
item.title.toLowerCase().includes(searchTerm) ||
item.content.toLowerCase().includes(searchTerm)
)
: items;
console.log('Filtered items:', newFilteredItems);
setFilteredItems(newFilteredItems);
};
return (
<div>
<Search onFilter={handleFilter} />
<AccordionList items={filteredItems} />
</div>
);
};
// Register the component with Builder.io
Builder.registerComponent(AccordionWithSearch, {
name: 'AccordionWithSearch',
inputs: [
{
name: 'items',
type: 'list',
subFields: [
{
name: 'title',
type: 'string',
required: true,
},
{
name: 'content',
type: 'string',
required: true,
},
],
},
],
});
export default AccordionWithSearch;
I have created a data model. Here are the API results. I am trying to connect the data from the visual editor.
{
"results": [
{
"lastUpdatedBy": "sReRVmTVQafbBfvBu8ZuFfFYHDi1",
"folders": [],
"data": {
"policies": [
{
"title": "Policy 1",
"content": "About the policy"
},
{
"title": "Policy 2",
"content": "About the policy"
},
{
"title": "Policy 3",
"content": "About the policy"
},
{
"title": "Policy 4",
"content": "About the policy"
},
{
"title": "Policy 5",
"content": "About the policy"
},
{
"title": "Policy 6",
"content": "About the policy"
},
{
"title": "Policy 6",
"content": "About the policy"
},
{
"title": "Policy 8",
"content": "About the policy"
}
]
},
"modelId": "b9446e7297f548c99c48ba94b848620e",
"query": [],
"published": "published",
"firstPublished": 1718201191076,
"testRatio": 1,
"lastUpdated": 1718201191133,
"createdDate": 1718201135132,
"createdBy": "sReRVmTVQafbBfvBu8ZuFfFYHDi1",
"meta": {
"kind": "data",
"lastPreviewUrl": ""
},
"variations": {},
"name": "Test Policies",
"id": "3084699391214e219613877eaff779f1",
"rev": "p5bkuac4q2"
}
]