I am trying to create accordion that when you click it will slide down and change the icon
Here is my following code in App.tsx
:
const accordionList = [
{
title: "Horses can..."
icon: "🐴",
pointer: "👈"
},
{
title: "Rhino skin maybe.."
icon: "🦏",
pointer: "👈"
},
{
title: "If you looking..."
icon: "🦄",
pointer: "👈"
}
]
function App() {
const [icon, setIcon] = useState(['👈'])
const toggleAccordion = (accordion: any, index: any) => {
const iconRotate = [...accordion.pointer];
iconRotate[accordion.pointer] = '👇';
setIcon(iconRotate[accordion.pointer])
accordion.pointer = icon;
}
return (
<div className="App">
<div className="App-header">
{accordionList.map((accordion, index) => (
<ul className="accordion-list" key={index}>
<div className="accordion-item">
<button onClick={() => toggleAccordion(accordion, index)}>{accordion.icon} {icon} </button>
<Accordion accordion={accordion} />
</div>
</ul>
))}
</div>
</div>
);
}
export default App;
and here is my following code in Accordion.tsx
:
interface Props {
accordion: { title: string, icon: string;}
}
export const Accordion: React.FC<Props> = (props) => {
const { accordion } = props;
return (
<div>
{accordion.title}
</div>
)
};
Right now my toggleAccordion
function didn't change the icon when it clicked. How can I improve my function?
Updated pointer to array of objects
From my understanding of what you're trying to accomplish, to change the icon, you just need to update the icon
state rather than updating the pointer inside your accordionList.pointer
and maintain this icon state for all the item in the icon list you have. I'll suggest you to divide your accordion item into its own component with the icon state like below:
The App.js
file:
const accordionList = [
{
title: "Horses can..."
icon: "🐴",
pointer: "👈"
},
{
title: "Rhino skin maybe.."
icon: "🦏",
pointer: "👈"
},
{
title: "If you looking..."
icon: "🦄",
pointer: "👈"
}
]
function App() {
return (
<div className="App">
<div className="App-header">
{accordionList.map((accordion, index) => (
<ul className="accordion-list" key={index}>
<AccordionItem accordion={accordion}/>
</ul>
))}
</div>
</div>
);
}
export default App;
The AccordionItem
component:
function AccordionItem({accordion}) {
const [indicatorIcon, setIndicatorIcon] = useState('👈')
const toggleAccordion = () => {
setIndicatorIcon('👇');
}
return (
<div className="accordion-item">
<button
onClick={() => toggleAccordion(accordion, index)}
>{accordion.icon} {icon} </button>
<Accordion accordion={accordion} />
</div>
);
}
export default App;
And you can keep your Accordion
as is. This will separate your concern, help you to only need to care about the state of the AccordionItem
, and this will remove any unnecessary complex array manipulation.