#javascript #reactjs
#javascript #reactjs
Вопрос:
я только начал с React и Next.js и я возился с крючками, и я застрял, я создал вертикальное меню, я хочу отображать содержимое под каждым заголовком, но только по одному, принимая во внимание эти 2 варианта:
- если я нажму заголовок, содержимое которого уже отображается, содержимое просто скроется.
- если я нажму на другой заголовок, содержимое последнего заголовка скроется, а содержимое нового заголовка появится под ним.
Большое вам спасибо за ваше время.
Я создал изолированную среду для базовой логики моего кода: https://codesandbox.io/s/affectionate-morning-tyj8j?file=/src/App.tsx
Тот же самый код — это:
import {useState} from "react";
export default function Test() {
const [content1, setContent1] = useState(null);
const [content2, setContent2] = useState(null);
const [content3, setContent3] = useState(null);
return (
<div>
<div onClick={() => setContent1(Content_1)}>
Click to show content 1
<div>
{content1}
</div>
</div>
<div onClick={() => setContent2(Content_2)}>
Click to show content 2
<div>
{content2}
</div>
</div>
<div onClick={() => setContent3(Content_3)}>
Click to show content 3
<div>
{content3}
</div>
</div>
</div>
)
}
const Content_1 = () => {
return (
<p>Content 1</p>
)
}
const Content_2 = () => {
return (
<p>Content 2</p>
)
}
const Content_3 = () => {
return (
<p>Content 3</p>
)
}
Ответ №1:
Вы должны сделать шаг назад и подумать немного более абстрактно о том, что означает ваше взаимодействие с пользовательским интерфейсом.
- если я нажму заголовок, содержимое которого уже отображается, содержимое просто скроется.
- если я нажму на другой заголовок, содержимое последнего заголовка скроется, а содержимое нового заголовка появится под ним.
Таким образом, у вас всегда будет только один раздел содержимого, открытый / видимый одновременно. Нет необходимости сохранять отдельные состояния для каждого раздела содержимого, который вы хотите переключить вручную, и по мере роста количества разделов содержимого вам нужно будет линейно увеличивать количество переключений. Это ужасно неэффективный способ масштабирования.
Я предлагаю использовать одно состояние для определения того, какой раздел содержимого активен. Используйте обработчик переключения, чтобы либо переключить обратно «закрытый» раздел, если его идентификатор установлен снова, в противном случае задайте новый идентификатор раздела. Условно отобразите раздел, если его идентификатор совпадает с активным идентификатором, установленным в состоянии.
function App() {
const [active, setActive] = useState<number>(-1);
const toggleHandler = (id: number) => () =>
setActive((active) => (active === id ? -1 : id));
return (
<div>
<div onClick={toggleHandler(1)}>
Click to show content 1{active === 1 amp;amp; <Content1 />}
</div>
<div onClick={toggleHandler(2)}>
Click to show content 2{active === 2 amp;amp; <Content2 />}
</div>
<div onClick={toggleHandler(3)}>
Click to show content 3{active === 3 amp;amp; <Content2 />}
</div>
</div>
);
}
Ответ №2:
Я использовал ту же структуру, чтобы вам было легче понять 🙂 Если у вас все еще возникают трудности, держите меня на связи.
Предлагаемый код
import React, { useState } from 'react';
export default function Test() {
// states
const [content1, setContent1] = useState(true);
const [content2, setContent2] = useState(false);
const [content3, setContent3] = useState(false);
// content
const Content_1 = <p>Content 1</p>;
const Content_2 = <p>Content 2</p>;
const Content_3 = <p>Content 3</p>;
function setContent(id) {
setContent1(id === 1);
setContent2(id === 2);
setContent3(id === 3);
}
return (
<div>
<button onClick={() => setContent(1)}>Show 1</button>
<button onClick={() => setContent(2)}>Show 2</button>
<button onClick={() => setContent(3)}>Show 3</button>
{content1 amp;amp; <div>{Content_1}</div>}
{content2 amp;amp; <div>{Content_2}</div>}
{content3 amp;amp; <div>{Content_3}</div>}
</div>
);
}
Комментарии:
1. Спасибо за вашу помощь! Но по какой-то причине код не работает в изолированной среде или в моей IDE, и я не могу понять, почему!
2. Я пытался упростить ваш код. Проверьте это!