#javascript #reactjs #typescript
#javascript #reactjs #typescript
Вопрос:
У меня есть функциональный компонент React, в котором есть список изображений с заголовками:
export function MyComponent() {
const images = [
{ image: "http://www.example1.com/image1.jpg", title: "Title 1"},
{ image: "http://www.example2.com/image2.jpg", title: "Title 2"},
{ image: "http://www.example3.com/image3.jpg", title: "Title 3"}
]
const [titles, setTitles] = React.useState([]);
return (
<div>
<div>{titles}</div>
<section className="images">{
images.map(image => (
<img
src={image.image}
alt={image.title}
onClick={() => {}} // selects or unselects the image?
/>
)
)}</section>
</div>
);
}
Когда я нажимаю на изображение, я хочу, чтобы оно было либо выделено, либо не выделено. Когда он выбран, я хочу, чтобы появилась граница CSS. Если выбрано изображение, я хочу, чтобы список выбранных заголовков изображений отображался в <div>{titles}</div>
. Я думал использовать React.useState()
здесь, но я не уверен, как это сделать. Я не хочу проводить рефакторинг для использования класса; это должен быть функциональный компонент. Спасибо.
Ответ №1:
Я предполагаю, что вы хотите выбирать по одному изображению за раз и отображать его заголовок. Итак, вот наивный подход, который вы можете адаптировать в соответствии с вашей ситуацией.
const images = [
{ image: "https://via.placeholder.com/150", title: "Title 1" },
{ image: "https://via.placeholder.com/150", title: "Title 2" },
{ image: "https://via.placeholder.com/150", title: "Title 3" },
];
function Main() {
const [selected, setSelected] = React.useState();
return (
<div>
<div>{images[selected] amp;amp; images[selected].title}</div>
<section className="images">
{images.map((image, index) => (
<img
className={index === selected ? "selected" : ""}
key={`${index}${image.title}`}
src={image.image}
alt={image.title}
onClick={() => setSelected(index)}
/>
))}
</section>
</div>
);
}
ReactDOM.render(<Main />, document.getElementById("root"));
.selected {
border: 5px solid black;
}
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root" />
Итак, у вас есть одно состояние, выбранное index
. Для className
части, которую вы ищете для изображения index
, сравните с selected
состоянием, затем назначьте имя класса в соответствии с этим. Для части заголовка вы просто захватываете, title
используя выделенный index
с условным JSX.
Но использование индексов ненадежно. Было бы лучше иметь несколько уникальных идентификаторов для изображений.
Ответ №2:
export function MyComponent() {
const images = [
{
image: 'http://www.example1.com/image1.jpg',
title: 'Title 1',
},
{
image: 'http://www.example2.com/image2.jpg',
title: 'Title 2',
},
{
image: 'http://www.example3.com/image3.jpg',
title: 'Title 3',
},
];
const [titles, setTitles] = React.useState([]);
return (
<div>
<div>{titles}</div>
<section className="images">
{images.map((image) => (
<img
style={{
border: titles.includes(image.title) ? '3px solid black' : 'none',
}}
src={image.image}
alt={image.title}
onClick={() => {
if (titles.includes(image.title)) {
setTitles(titles.filter((title) => title !== image.title));
} else setTitles([...titles, image.title]);
}}
/>
))}
</section>
</div>
);
}