Implementación paso a paso de la función Expandir/Contraer en React

Irakli Tchigladze 8 octubre 2023
  1. Implementar una función de expandir/contraer en React
  2. Expandir/contraer todo el contenedor en React
  3. Expandir/contraer publicaciones específicas en React
  4. Expandir o contraer todas las publicaciones en React
  5. Conclusión
Implementación paso a paso de la función Expandir/Contraer en React

Al crear aplicaciones web, a menudo necesita cambiar dinámicamente la apariencia de un elemento específico en DOM.

Otras veces, necesita mostrar contenido solo cuando el usuario quiere verlo. Esto puede ayudarlo a administrar grandes volúmenes de contenido sin abrumar al usuario y brindar una buena experiencia de usuario.

En este artículo, queremos mostrarle cómo implementar la función de expandir/contraer para mostrar u ocultar contenedores en respuesta al clic de un botón por parte del usuario.

Implementar una función de expandir/contraer en React

React te permite ocultar y mostrar componentes de forma condicional. Que un componente se represente o no dependerá del valor de la variable de estado, que se puede cambiar en respuesta a las acciones del usuario.

Puede almacenar una variable de estado del tipo booleano. En JSX, puede usar un operador ternario (o usar una condición if dentro de una función) para determinar condicionalmente si ciertos elementos DOM (o componentes) deben representarse o no.

Comencemos mirando un ejemplo: tenemos un componente principal que muestra una lista de publicaciones representadas por el componente <Publicación>.

import "./styles.css";
import { useState } from "react";
export default function App() {
  let postsArr = ["post1", "post2", "post3", "post4", "post5"];
  const [postDisplay, setPostDisplay] = useState({
    post1: true,
    post2: true,
    post3: true,
    post4: true,
    post5: true
  });
  const [divDisplay, setDivDisplay] = useState(true);
  const handleClick = (post) => {
    const objectCopy = {
      ...postDisplay
    };
    objectCopy[post] = !objectCopy[post];
    setPostDisplay(objectCopy);
  };
  return (
    <div className="App">
      <button
        onClick={() =>
          setPostDisplay({
            post1: false,
            post2: false,
            post3: false,
            post4: false,
            post5: false
          })
        }
      >
        Hide All Posts
      </button>
      <br />
      <button
        onClick={() =>
          setPostDisplay({
            post1: true,
            post2: true,
            post3: true,
            post4: true,
            post5: true
          })
        }
      >
        Show All Posts
      </button>
      <br />
      <button onClick={() => setDivDisplay(!divDisplay)}>
        Expand/Collapse the post section
      </button>
      {postsArr.map((post) =>
        divDisplay ? (
          <div>
            <button onClick={() => handleClick(post)}>Expand {post}</button>
            {postDisplay[post] ? <Post key={post}></Post> : null}
          </div>
        ) : null
      )}
    </div>
  );
}

function Post() {
  return (
    <div className="post">
      <p>
        Some content
      </p>
    </div>
  );
}

En este caso, en lugar de tener una variable de estado booleana, tenemos un objeto de valores booleanos, uno para cada publicación. Esto nos permite expandir solo algunas publicaciones y mantener otras colapsadas (ocultas).

Antes de desglosar brevemente este código, puede verificar la funcionalidad dinámica de expandir/contraer en CodeSandbox.

Dentro de nuestro componente Aplicación, tenemos una variedad de publicaciones. En JSX, aplicamos un método .map() a la matriz postsArr y condicionalmente verificamos si debemos mostrar el contenedor completo de publicaciones o publicaciones individuales.

let postsArr = ["post1", "post2", "post3", "post4", "post5"];
...
{postsArr.map((post) =>
        divDisplay ? (
          <div>
            <button onClick={() => handleClick(post)}>Expand {post}</button>
            {postDisplay[post] ? <Post key={post}></Post> : null}
          </div>
        ) : null
)}

Expandir/contraer todo el contenedor en React

Primero, verificamos el valor de divDisplay para determinar si debemos representar el elemento <div> que contiene los componentes <Post />. Si visita la demostración en vivo de CodeSandbox, verá que tenemos un botón.

Al hacer clic en este botón, se cambiará el valor actual de la variable de estado divDisplay. Si el contenedor <div> está contraído, al hacer clic en este botón se expandirá.

Si está expandido, al hacer clic en el botón se ocultará el contenedor. Veamos el código de este botón.

<button onClick={() => setDivDisplay(!divDisplay)}>
        Expand/Collapse the post section
</button>

Establecemos un atributo onClick en el elemento <button> y establecemos su valor en una función de flecha simple que hará una llamada a la función setDivDisplay(), que actualiza la variable de estado divDisplay. Definimos la función de actualización usando el enlace useState.

const [divDisplay, setDivDisplay] = useState(true);

Establecemos por defecto el valor de la variable divDisplay en true. Más tarde, los usuarios pueden cambiar el valor de esta variable haciendo clic en el botón.

Expandir/contraer publicaciones específicas en React

Suponiendo que expandimos todo el elemento <div> que contiene publicaciones, también podemos expandir o contraer publicaciones individuales, que ocultan o muestran el contenido de la publicación.

Veamos la sección de código donde generamos los componentes <Post>.

{postsArr.map((post) =>
        divDisplay ? (
          <div>
            <button onClick={() => handleClick(post)}>Expand {post}</button>
            {postDisplay[post] ? <Post key={post}></Post> : null}
          </div>
        ) : null
)}

Aplicamos un método map() en la matriz postsArr y devolvemos un elemento <div> que almacena un botón para mostrar/ocultar el botón y un operador ternario que verifica el valor del objeto postDisplay para la propiedad de cada elemento de la matriz.

Puede ser confuso, pero echemos un vistazo a la matriz y las variables de estado nuevamente.

let postsArr = ["post1", "post2", "post3", "post4", "post5"];

const [postDisplay, setPostDisplay] = useState({
    post1: true,
    post2: true,
    post3: true,
    post4: true,
    post5: true
  });

Como sabrá, el método map() tomará cada cadena en la matriz. Luego comprobará el valor de esta propiedad en el objeto postDisplay.

Por ejemplo, el primer método map() tomará la cadena 'post1' y representará un componente <Post> comprobando el valor de la expresión postDisplay['post1'].

{postDisplay[post] ? <Post key={post}></Post> : null}

Tenga en cuenta que el método map() toma la función de devolución de llamada como argumento y trata cada elemento de la matriz como una variable. Por lo tanto, necesitamos usar la notación de paréntesis para buscar el valor de la propiedad.

El operador ternario devuelve nulo si el valor de la propiedad es falso, lo que no genera nada.

Vaya a la demostración de CodeSandbox e intente expandir y contraer publicaciones individuales haciendo clic en un botón. Usar el formato de objeto nos permite expandir el contenido de algunas publicaciones mientras mantiene otras colapsadas.

Expandir o contraer todas las publicaciones en React

En la parte superior de la página, tenemos dos botones: el primero contrae todas las publicaciones que pueden estar expandidas actualmente y el segundo expande todas las publicaciones. Intente hacer clic en estos botones en la demostración en vivo para comprender mejor su funcionalidad.

Ahora veamos cómo se logra esto dentro de React.

<button
	onClick={() =>
	  setPostDisplay({
		post1: false,
		post2: false,
		post3: false,
		post4: false,
		post5: false
	  })
	}
  >
	Hide All Posts
  </button>
  <br />
  <button
	onClick={() =>
	  setPostDisplay({
		post1: true,
		post2: true,
		post3: true,
		post4: true,
		post5: true
	  })
	}
  >
	Show All Posts
  </button>

Establecemos el atributo onClick, por lo que cada vez que el usuario hace clic en el primer botón, llamamos a la función setPostDisplay() con un objeto donde los valores de todas las propiedades (correspondientes al estado de las publicaciones individuales) se establecen en false .

El segundo botón hace lo mismo, pero todas las propiedades del objeto se establecen en “true” en este caso. Por lo tanto, al hacer clic en estos botones se expandirá el contenido de todas las publicaciones.

Conclusión

Este es un ejemplo muy simple; por lo general, los sitios web tienen botones más elegantes para expandir y contraer contenedores en React. Los estilos de los botones pueden diferir, pero la implementación funcional será la misma o muy similar a la que mostramos aquí.

Irakli Tchigladze avatar Irakli Tchigladze avatar

Irakli is a writer who loves computers and helping people solve their technical problems. He lives in Georgia and enjoys spending time with animals.

LinkedIn