Как скрыть и показать компоненты с помощью useState или условного рендеринга в React?

Моя первоначальная цель решить:

  • У меня есть 4 компонента, выстроенные рядом друг с другом. Я хочу иметь возможность переключать/нажимать один из компонентов, а остальные 3 компонента исчезают. Затем повторное переключение того же компонента, чтобы снова появились другие компоненты. Но также иметь возможность выполнять ту же задачу, переключая любой из других компонентов.
  • Проще говоря, каждый из компонентов представляет собой тег div с тегом изображения внутри.

Мой первоначальный взгляд на проблему:

export const Test = () => {
    const intialValue = [{id: 0, component: null}]
    const array = [
                    {id: 1, component: <CompOne/>}, 
                    {id: 2, component: <CompTwo/>}, 
                    {id: 3, component: <CompThree/>}, 
                    {id: 4, component: <CompFour/>}
                  ]
    
    const [chosenNumber, setChosen] = useState(0)
    const [statearray, setArray] = useState(array)

    useEffect(() => {
        console.info(chosenNumber)
        const arr = array
        if (chosenNumber === 0 ) setArray(array)
        else setArray(arr.filter( num => num === chosenNumber))
    }, [chosenNumber])

    const handleClick = (number) => {
        if (number === chosenNumber) setChosen(0)
        else setChosen(number)
    }
        return (
            <div className = "flex" >
                {statearray.map((comp, number) => <div key = {number} className = "h-12 w-12 bg-gray-400 m-1 flex items-center justify-center" onClick = {() => handleClick(comp.id)}>{comp.id}</div>)}
            </div>
        );

}

Мой мыслительный процесс заключается в том, что когда я щелкаю компонент (div), я устанавливаю selectedNumber, если div, который я щелкнул, совпадает с выбранным, сбросить выбранное до нуля.

Каждый раз, когда selectedNumber изменяется, useEffect должен обнаружить это и отфильтровать массив с selectedNumber, если selected равен нулю, сбросить stateArray.

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

Спасибо за помощь!

что ты уже испробовал?

clod9353 10.12.2020 17:40

Если вы хотите получить помощь, покажите нам, что вы хотя бы пытались решить ее самостоятельно, предоставив фрагменты кода и где вы потенциально застряли. Мы не решим это за вас, но мы поможем вам, если вы попытаетесь.

Mantas Astra 10.12.2020 17:40

@MantasAstra Я только что обновил свой вопрос. Я извиняюсь за то, как изначально я написал свой вопрос

Patrik Kozak 10.12.2020 18:01

@ clod9353 Я обновил свой вопрос. Надеюсь, это лучший формат. Прошу прощения за фразу в начале.

Patrik Kozak 10.12.2020 18:11
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
5
4
1 749
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Один из простых способов — сохранить логическое значение в состоянии (например, isVisible = true) либо в useState, либо в mobx и т. д. Затем в компоненте реакции вы можете использовать двойной амперсанд, как показано ниже:

{isVisible && <MyComponent/>}

Это будет отображаться только в том случае, если isVisible = true

Спасибо за ответ! Это был мой первоначальный взгляд на проблему, но у меня были трудности с обновлением состояния каждого компонента в том смысле, что если компонент 1 переключается, сделать компоненты 2-4 невидимыми (false), а затем повторить эту логику для другие компоненты. Надеюсь, это имеет смысл.

Patrik Kozak 10.12.2020 18:15
const [currentComponent, setCurrentComponent] = useState(1);

const handleClick = () =>{
    switch(currentComponent){
        case 1:
            setCurrentComponent(2)
        case 2:
            setCurrentComponent(3)
        case 3:
            setCurrentComponent(4)
        case 4:
            setCurrentComponent(1)

    }
}


<button onClick = {()=> handleClick()}>Click me!</button>


{currentComponent == 1 && <Comp1/>};
{currentComponent == 2 && <Comp2/>};
{currentComponent == 3 && <Comp3/>};
{currentComponent == 4 && <Comp4/>};

Я ценю пример! Я повторно обновил свой вопрос, чтобы включить мой первоначальный подход к проблеме. Я пытался использовать ваше решение, но у меня возникли проблемы с его реализацией. Кнопка ничего не делает, и виден только первый компонент.

Patrik Kozak 10.12.2020 18:07

Извини! Забыл добавить перерыв; в конце каждого case в операторе switch. Попробуй это

Josh Merrian 10.12.2020 21:31
Ответ принят как подходящий

На вашем месте я бы все упростил. Во-первых, я бы извлек array из компонента, так как вы не хотите, чтобы он повторно отображался каждый раз при повторном отображении компонента. Затем я бы изменил ваше состояние и оставил только состояние items, которое будет содержать array элементы. Я бы также расширил элементы array, добавив флаг isVisible. Затем я бы удалил ваш useEffect и улучшил handleClick, поскольку вы хотите, чтобы это вызывалось только при нажатии кнопки. В функции handleClick я бы создал новый набор элементов, сопоставив ваш items и изменив «не нажатые» элементы isVisible на false. Таким образом, вы знаете, какие предметы нужно спрятать. Наконец, я бы визуализировал компоненты на основе атрибута isVisible. Таким образом, если isVisible истинно, элемент будет отображаться с hidden, установленным на false, и наоборот.

Таким образом, код становится намного проще, производительнее и понятнее. Кроме того, он делает то, что вы просили.

Вот ссылка на пример рабочего кода: codeandbox

import React, { useState } from "react";

const Comp1 = () => <div>hi</div>;
const Comp2 = () => <div>hi2</div>;
const Comp3 = () => <div>hi3</div>;

const array = [
  { id: 1, component: <Comp1 />, isVisible: true },
  { id: 2, component: <Comp2 />, isVisible: true },
  { id: 3, component: <Comp3 />, isVisible: true }
];

export const Test = () => {
  const [items, setItems] = useState(array);

  const handleClick = (number) => {
    const triggeredItems = items.map((item) => {
      if (item.id !== number) {
        item.isVisible = !item.isVisible;
      }

      return item;
    });

    setItems(triggeredItems);
  };

  return (
    <div className = "flex">
      {items.map(({ id, component, isVisible }) => (
        <div
          key = {id}
          className = "h-12 w-12 bg-gray-400 m-1 flex items-center justify-center"
          onClick = {() => handleClick(id)}
          hidden = {!isVisible}
        >
          {component}
        </div>
      ))}
    </div>
  );
};

export default Test;

Спасибо за пример и совет. Я очень ценю это. На данный момент это выводит идентификатор каждого компонента, но в идеале нужно, чтобы тег div, соответствующий идентификатору, был тем, что печатается. Я понимаю, что функция карты принимает идентификатор в качестве индекса для индексации массива, но я бы хотел, чтобы div были видимыми или невидимыми. Есть предположения?

Patrik Kozak 10.12.2020 18:45

Вы по-прежнему можете применять ту же технику, пока вы обертываете компоненты div или чем-то еще, чтобы вы могли включать и выключать их. Я отредактировал свой первоначальный ответ с примером, который принимает компоненты и отображает их. @PatrikKozak

Mantas Astra 10.12.2020 18:50

Мне просто нужно было добавить «компонент» в функцию карты. Еще раз спасибо за помощь!

Patrik Kozak 10.12.2020 18:51

Я хочу добавить новый объект/элемент в соответствии с каждым конкретным объектом в массиве, например, «описание» указанного компонента, и я хочу, чтобы их описание отображалось только при нажатии на один из компонентов. Если я создаю массив внутри каждого объекта этого исходного массива, который содержит информацию «описание», я могу отображать информацию, когда присутствует каждый объект, в других мирах всегда «isVisible = true». Но он должен начинаться как false, затем при щелчке компонента измениться на true, а при повторном щелчке компонента снова изменить его на false. Я не могу понять эту часть.

Patrik Kozak 10.12.2020 23:06

Другие вопросы по теме