Cómo crear un componente de acordeón con React

Introducción
El instrumento musical acordeón se comprime y se expande. El elemento de control gráfico acordeón se contrae y se expande de manera similar. Esta puede ser una solución para dividir contenido extenso y permitir que los usuarios se concentren en las secciones que son relevantes para ellos.
De manera similar a un componente de pestañas , un componente de acordeón se compone de diferentes secciones que se pueden abrir y cerrar. A diferencia de un componente de pestañas, los acordeones pueden mostrar varias secciones de contenido al mismo tiempo.
En este artículo, creará un componente de acordeón simple y reutilizable con secciones que se pueden abrir y cerrar. Luego, modificaremos el componente para que admita tener varias secciones abiertas a la vez y especificaremos qué secciones deben estar abiertas de forma predeterminada.
Prerrequisitos
Para completar este tutorial, necesitarás:
- Node.js instalado localmente, lo cual puedes hacer siguiendo Cómo instalar Node.js y crear un entorno de desarrollo local .
- Si tienes alguna familiaridad con React, puedes echar un vistazo a nuestra serie Cómo programar en React.js .
Este tutorial fue verificado con Node v16.6.2, npm
v7.21.0 y react
v17.0.2.
Paso 1: Configuración del proyecto
En este paso, crearás un nuevo proyecto con Create React App . Luego, eliminarás el proyecto de muestra y los archivos relacionados que se instalan cuando inicias el proyecto.
Para comenzar, crea un nuevo proyecto. En tu terminal, ejecuta el siguiente script para instalar un nuevo proyecto usando create-react-app
:
- npx create-react-app react-accordion-component
Una vez finalizado el proyecto, cambie al directorio:
- cd react-accordion-component
En una nueva pestaña o ventana de la terminal, inicia el proyecto con el script de inicio Create React App . El navegador se actualizará automáticamente cuando se produzcan cambios, así que deja este script ejecutándose mientras trabajas:
- npm start
Esto iniciará un servidor que se ejecuta localmente. Si el proyecto no se abrió en una ventana del navegador, puede abrirlo visitando http://localhost:3000/
. Si está ejecutando esto desde un servidor remoto, la dirección será .http://your_domain:3000
Su navegador se cargará con una plantilla de aplicación React incluida como parte de Create React App:
Construirás un conjunto completamente nuevo de componentes personalizados, por lo que tendrás que comenzar borrando parte del código repetitivo para poder tener un proyecto vacío.
Para comenzar, abre src/App.js
un editor de texto. Este es el componente raíz que se inyecta en la página. Todos los componentes comenzarán desde aquí. Puedes encontrar más información sobre App.js
Cómo configurar un proyecto de React con Create React App .
Verás un archivo como este:
fuente/App.js
import logo from './logo.svg';import './App.css';function App() { return ( div className="App" header className="App-header" img src={logo} className="App-logo" alt="logo" / p Edit codesrc/App.js/code and save to reload. /p a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" Learn React /a /header /div );}export default App;
Elimine la línea import logo from './logo.svg';
. Luego reemplace todo en la return
declaración para devolver un conjunto de div
etiquetas y un h1
. Esto le dará una página válida que devuelve un h1
que muestra Accordion Demo . El código final se verá así:
fuente/App.js
import './App.css';function App() { return ( div h1Accordion Demo/h1 /div );}export default App;
Guardar y salir del editor de texto.
Por último, elimine el logotipo. No lo utilizará en su aplicación y deberá eliminar los archivos que no utilice a medida que trabaja. Esto le evitará confusiones a largo plazo.
En la ventana de terminal escriba el siguiente comando para eliminar el logotipo:
- rm src/logo.svg
Ahora que el proyecto está configurado, puedes crear tu primer componente.
Paso 2: Construcción de los componentes
Crearemos tres componentes:
Accordion
:que contendrá los componentes de nuestra sección y administrará qué secciones están abiertas y cerradas.AccordionSection
:que mostrará el título de la sección en la que se puede hacer clic, el contenido de la sección cuando la sección esté abierta e informará acerca de losAccordion
eventos de clic.App
:¡componente para unir todo en un ejemplo funcional!
Las secciones dentro del Accordion
componente serán simplemente div
etiquetas que recibirán un label
atributo que se utilizará para la región en la que se puede hacer clic dentro del AccordionSection
componente.
Comencemos creando nuestro componente más interno AccordionSection
:
src/AccordionSection.js
import React from 'react';import PropTypes from 'prop-types';class AccordionSection extends React.Component { static propTypes = { children: PropTypes.instanceOf(Object).isRequired, isOpen: PropTypes.bool.isRequired, label: PropTypes.string.isRequired, onClick: PropTypes.func.isRequired, }; onClick = () = { this.props.onClick(this.props.label); }; render() { const { onClick, props: { isOpen, label }, } = this; return ( div style={{ background: isOpen ? '#fae042' : '#6db65b', border: '1px solid #008f68', padding: '5px 10px', }} div onClick={onClick} style={{ cursor: 'pointer' }} {label} div style={{ float: 'right' }} {!isOpen span#9650;/span} {isOpen span#9660;/span} /div /div {isOpen ( div style={{ background: '#6db65b', border: '2px solid #008f68', marginTop: 10, padding: '10px 20px', }} {this.props.children} /div )} /div ); }}export default AccordionSection;
Este componente recibirá una label
propiedad que creará el título en el que se puede hacer clic de la sección. La onClick
propiedad del controlador de eventos se utiliza para informar al componente principal si se ha hecho clic en la etiqueta.
El componente principal se encargará de realizar el seguimiento de qué secciones están abiertas o cerradas y enviará el estado AccordionSection
como una propiedad booleana isOpen
.
Cualquier componente secundario AccordionSection
se mostrará solo si la sección se ha activado para abrir y la propiedad isOpen
es verdadera.
Ahora que tenemos un componente para nuestras secciones, necesitamos un componente que albergue estas secciones y administre el estado de qué secciones se han abierto o cerrado:
fuente/Accordion.js
import React from 'react';import PropTypes from 'prop-types';import AccordionSection from './AccordionSection';class Accordion extends React.Component { static propTypes = { children: PropTypes.instanceOf(Object).isRequired, }; constructor(props) { super(props); const openSections = {}; this.state = { openSections }; } onClick = label = { const { state: { openSections }, } = this; const isOpen = !!openSections[label]; this.setState({ openSections: { [label]: !isOpen } }); }; render() { const { onClick, props: { children }, state: { openSections }, } = this; return ( div style={{ border: '2px solid #008f68' }} {children.map(child = ( AccordionSection isOpen={!!openSections[child.props.label]} label={child.props.label} onClick={onClick} {child.props.children} /AccordionSection ))} /div ); }}export default Accordion;
¡Genial! Nuestro Accordion
componente recibirá nodos secundarios que se utilizarán para crear nuestros AccordionSection
componentes interactivos.
Este componente rastrea qué sección se ha abierto, pero solo mantiene un registro de una sola sección abierta a la vez (por ahora).
¡Una vez creados nuestros componentes Accordion
y AccordionSection
, ahora podemos crear nuestro App
componente y ver las cosas en acción!
Para nuestra demostración de acordeón, crearemos un acordeón Accordion
con dos componentes secundarios que contienen algunos datos sobre los caimanes:
fuente/App.js
import Accordion from './Accordion';function App() { return ( div h1Accordion Demo/h1 Accordion div label='Alligator Mississippiensis' p strongCommon Name:/strong American Alligator /p p strongDistribution:/strong Texas to North Carolina, US /p p strongEndangered Status:/strong Currently Not Endangered /p /div div label='Alligator Sinensis' p strongCommon Name:/strong Chinese Alligator /p p strongDistribution:/strong Eastern China /p p strongEndangered Status:/strong Critically Endangered /p /div /Accordion /div );}export default App;
Contiene Accordion
dos secciones que, al hacer clic para abrirlas, mostrarán algunos datos sobre diferentes especies de caimanes.
Paso 3: Compatibilidad con múltiples acordeones abiertos
Todo lo que hemos creado hasta ahora es utilizable, pero algo limitado, ya que solo se puede abrir una sección a la vez y todas las secciones están contraídas de forma predeterminada.
Para agregar soporte para que múltiples secciones estén abiertas al mismo tiempo, vamos a agregar una propiedad llamada allowMultipleOpen
al Accordion
componente que se usará para indicarle al acordeón si debe permitir que múltiples secciones estén abiertas.
Cuando está habilitado, el estado alternará las claves individuales entre verdadero y falso en lugar de sobrescribir completamente el estado con la sección con la que se interactuó.
Mientras estamos allí, podemos agregar algo de lógica adicional para verificar los nodos secundarios en busca de una isOpen
propiedad. Cuando esté presente, el estado abierto se inicializará y la sección ya estará marcada como abierta:
fuente/Accordion.js
import React from 'react';import PropTypes from 'prop-types';import AccordionSection from './AccordionSection';class Accordion extends React.Component { static propTypes = { allowMultipleOpen: PropTypes.bool, children: PropTypes.instanceOf(Object).isRequired, }; constructor(props) { super(props); const openSections = {}; this.props.children.forEach(child = { if (child.props.isOpen) { openSections[child.props.label] = true; } }); this.state = { openSections }; } onClick = label = { const { props: { allowMultipleOpen }, state: { openSections }, } = this; const isOpen = !!openSections[label]; if (allowMultipleOpen) { this.setState({ openSections: { ...openSections, [label]: !isOpen } }); } else { this.setState({ openSections: { [label]: !isOpen } }); } }; render() { const { onClick, props: { children }, state: { openSections }, } = this; return ( div style={{ border: '2px solid #008f68' }} {children.map(child = ( AccordionSection isOpen={!!openSections[child.props.label]} label={child.props.label} onClick={onClick} {child.props.children} /AccordionSection ))} /div ); }}export default Accordion;
Una vez que estamos Accordion
listos para aceptar nuevos parámetros, podemos actualizar nuestro App
componente para pasar la propiedad y permitir que se abran varias secciones, así como marcar la primera sección para que se abra de manera predeterminada:
fuente/App.js
import Accordion from './Accordion';function App() { return ( div h1Accordion Demo/h1 Accordion allowMultipleOpen div label='Alligator Mississippiensis' isOpen p strongCommon Name:/strong American Alligator /p p strongDistribution:/strong Texas to North Carolina, US /p p strongEndangered Status:/strong Currently Not Endangered /p /div div label='Alligator Sinensis' p strongCommon Name:/strong Chinese Alligator /p p strongDistribution:/strong Eastern China /p p strongEndangered Status:/strong Critically Endangered /p /div /Accordion /div );}export default App;
Ahí lo tienes, un componente de acordeón reutilizable que te ayudará a controlar el contenido rebelde.
Conclusión
En este artículo, creó un componente de acordeón simple y reutilizable con secciones que se pueden abrir y cerrar.
Continúa tu aprendizaje anidando estos acordeones para satisfacer incluso los escenarios más complejos.
Puede encontrar una demostración funcional y el código de este artículo en CodeSandbox .
Deja una respuesta