Я делаю простое приложение-аккордеон Reactjs, в котором выполняется сворачивание и развертывание каждого отдельного элемента.

< Сильный > Требования :

Простое требование заключается в том, что мне нужно переключать текст заголовка на Развернуть или Сжать в зависимости от щелчка.

Если мы щелкнем по любому элементу, то содержимое будет отображаться, в этом случае текст изменится на «Сжать», так как аккордеон открывается, поэтому для закрытия «аккордеона» дается заголовок «Сжатие».

Полный рабочий пример:

https://codesandbox.io/s/react-accordion-forked-lcyr0

В приведенном выше примере я использовал следующий код для изменения текста,

Accordion.js

import React, { useState } from "react";
import Text from "./text";
import Heading from "./heading";
import getAccordion from "./GetAccordion";

const Accordion = getAccordion(1);

const accordionData = [
  {
    id: 1,
    content: "This is a first content"
  },
  {
    id: 2,
    content: "This is a second content"
  },
  {
    id: 3,
    content: "This is a third content"
  }
];

const NormalAccordion = () => {
  const [toggleValue, setToggleValue] = useState(-1);

  const toggleHandler = (index) => {
    setToggleValue(index);
  };

  return (
    <div>
      {accordionData.map((item, index) => (
        <Accordion>
          <Heading>
            <div
              style={{ padding: "10px", cursor: "pointer" }}
              className="heading"
              onClick={() => toggleHandler(index)}
            >
              {toggleValue !== index ? `Expand` : `Shrink`}
            </div>
          </Heading>
          <Text>{item.content}</Text>
        </Accordion>
      ))}
    </div>
  );
};

export default NormalAccordion;

И эта строка {toggleValue !== index ? `Expand` : `Shrink`} меняет текст один раз, но после этого не вносит никаких изменений при дальнейшем переключении заголовка (Expand / Shrink).

Пожалуйста, помогите мне добиться результата переключения текста между расширением и сжатием на основе соответствующих щелчков.

3
Undefined 31 Авг 2020 в 13:57

2 ответа

Лучший ответ

Вы должны сбросить toggleValue, если элемент уже был нажат:

  const toggleHandler = (index) => {

    index===toggleValue?setToggleValue(-1): setToggleValue(index);
  };

Затем используйте условие для рендеринга текущего содержимого:

<Text>{toggleValue === index && item.content}</Text>

И упростим компонент Text до этого:

<div style={{ ...this.props.style }}>
        <div className={`content ${this.props.text ? "open" : ""}`}>
          {this.props.children}
        </div>
      </div>
2
Boussadjra Brahim 31 Авг 2020 в 11:45

Вы должны использовать логическое значение, так как аккордеон может иметь 2 значения.

Идея:

  • Создайте автономный компонент Accourdion, который определяет поведение разворачивания / сворачивания.
  • Создайте компонент представления оболочки, который вызывает этот компонент.
  • Передайте свои данные в качестве опоры из этого представления вместо использования локального жестко запрограммированного объекта.

Преимущество этого подхода состоит в том, что у вас есть 2 модульных компонента, которые работают только на реквизитах. Позже их можно экспортировать в отдельную библиотеку.

В идеале компонент должен быть глупым и должен знать только свое собственное поведение, основанное на состоянии и свойствах.

Обновленная песочница

  • Изменения аккордеонного компонента
const [toggleValue, setToggleValue] = useState(false);

const toggleHandler = () => {
  setToggleValue(!toggleValue);
};
  • Изменения вида аккордеона
const AccordionView = ({ accordionData }) => {
  return (
    <div>
      {accordionData.map((item) => (
        <NormalAccordion content={item.content} />
      ))}
    </div>
  );
};
  • Константы: я создаю папку, называемую константами, в которой будут храниться жестко запрограммированные объекты, а затем мы передаем ее, используя реквизиты из index.js
export const accordionData = [{
    id: 1,
    content: "This is a first content"
  },
  {
    id: 2,
    content: "This is a second content"
  },
  {
    id: 3,
    content: "This is a third content"
  }
];
  • Изменения в index.js
import { accordionData } from '../constants/accordion-data'

...

<NormalAccordion accordionData={ accordionData } />
2
Rajesh 31 Авг 2020 в 11:38