#reactjs
#reactjs
Вопрос:
Я совсем новичок в React и пытаюсь добавить точки разбиения на страницы в компонент carousel, который я создал с помощью react-swipable. Из документации, доступной для прокрутки, я уже реализовал рабочие кнопки next / previous, но я не могу понять, как реализовать точки разбивки на страницы в том же формате.
Я не уверен, правильно ли я думаю, но я подумал, что если бы я мог прочитать индекс отображаемых элементов, я мог бы использовать его, чтобы показать нужный элемент по его индексу.
Компонент использует редуктор, и я застрял на получении индекса из отображаемых элементов в инструкции switch и использую его там. Я думаю, что я просто не смотрю в правильном направлении, потому что я перепробовал все, что мог придумать, и часами гуглил, пытаясь найти ответ, не найдя вообще никаких похожих ситуаций / вопросов. У кого-нибудь из вас есть идея о том, как показать правильный слайд в соответствии с нумерацией страниц-нажатой кнопкой? (таким образом, нажатие второй кнопки разбивки на страницы должно показать второй слайд)
Итак, я добавил регистр точек к оператору switch, внутри которого есть оператор if, чтобы решить, следует ли перемещаться в следующем или предыдущем направлении. Затем я хотел, чтобы ‘pos’ изменился на индекс выбранных элементов.
Извините, если это глупый вопрос, я всего лишь новичок, и иногда это немного сбивает меня с толку.
Вот мой код:
import React, { useState } from "react";
import styled from "styled-components";
import { Swipeable } from "react-swipeable";
const NEXT = "NEXT";
const PREV = "PREV";
const DOT = "DOT";
function getOrder({ index, pos, numItems }) {
return index - pos < 0 ? numItems - Math.abs(index - pos) : index - pos;
}
const initialState = { pos: 0, sliding: false, dir: NEXT };
const CarouselContainer = styled.ul`
display: flex;
transition: ${(props) => (props.sliding ? "none" : "transform 1s ease")};
transform: ${(props) => {
if (!props.sliding) return "translateX(calc(-100%))";
if (props.dir === PREV) return "translateX(calc(2 * (-100%)))";
return "translateX(0%)";
}};
`;
function Carousel(props) {
const [state, dispatch] = React.useReducer(reducer, initialState);
const numItems = React.Children.count(props.children);
const index = props.children;
function Slide(dir) {
dispatch({ type: dir, numItems });
setTimeout(() => {
dispatch({ type: "stopSliding" });
}, 50);
}
const config = {
onSwipedLeft: () => Slide(NEXT),
onSwipedRight: () => Slide(PREV),
preventDefaultTouchmoveEvent: true,
trackMouse: true,
};
return (
<Swipeable {...config}>
<div>
<CarouselContainer dir={state.dir} sliding={state.sliding}>
{React.Children.map(props.children, (child, index) => (
<li
key={index}
order={getOrder({ index: index, pos: state.pos, numItems })}
style={{ order: `${getOrder({ index: index, pos: state.pos, numItems })}` }}
>
{child}
</li>
))}
</CarouselContainer>
</div>
<ul>
<li onClick={() => Slide(PREV)}>Vorige</li>
<li onClick={() => Slide(NEXT)}>Volgende</li>
</ul>
<ul className={styles.pagination}>
{React.Children.map(props.children, (dot, index) => (
<li
key={index}
onClick={() => {
Slide(DOT);
}}
>
{dot}
</li>
))}
</ul>
</Swipeable>
);
}
function reducer(state, { type, numItems }) {
switch (type) {
case "reset":
return initialState;
case PREV:
return {
...state,
dir: PREV,
sliding: true,
pos: state.pos === 0 ? numItems - 1 : state.pos - 1,
};
case NEXT:
return {
...state,
dir: NEXT,
sliding: true,
pos: state.pos === numItems - 1 ? 0 : state.pos 1,
};
case DOT:
if (state.pos > state.index) {
return {
...state,
dir: PREV,
sliding: true,
pos: state.index,
};
if (state.pos < state.index) {
return {
...state,
dir: NEXT,
sliding: true,
pos: state.index,
};
}
case "stopSliding":
return { ...state, sliding: false };
default:
return state;
}
}
export default Carousel;
Комментарии:
1. Почему вы просто не можете передать индекс функции Slide следующим образом: Slide (ТОЧКА, индекс); а затем отправить его в reducer и использовать его где угодно. Будет ли это работать для вас?
2. @Telary Спасибо вам! иногда мне не хватает такой мелочи! Я действительно пробовал это, но допустил ошибку при отправке. Теперь это наконец работает! Я счастлив 🙂
Ответ №1:
подсказка @ Telary помогла мне решить проблему! Я не могу пометить его комментарий как ответ, так что вот он:
function Carousel(props) {
const [state, dispatch] = React.useReducer(reducer, initialState);
const numItems = React.Children.count(props.children);
const index = props.children;
function Slide(dir, index) {
dispatch({ type: dir, numItems, index });
setTimeout(() => {
dispatch({ type: "stopSliding" });
}, 50);
}
const config = {
onSwipedLeft: () => Slide(NEXT),
onSwipedRight: () => Slide(PREV),
preventDefaultTouchmoveEvent: true,
trackMouse: true,
};
return (
<Swipeable {...config}>
<div>
<CarouselContainer dir={state.dir} sliding={state.sliding}>
{React.Children.map(props.children, (child, index) => (
<li
key={index}
order={getOrder({ index: index, pos: state.pos, numItems })}
style={{ order: `${getOrder({ index: index, pos: state.pos, numItems })}` }}
>
{child}
</li>
))}
</CarouselContainer>
</div>
<ul>
<li onClick={() => Slide(PREV)}>Vorige</li>
<li onClick={() => Slide(NEXT)}>Volgende</li>
</ul>
<ul className={styles.pagination}>
{React.Children.map(props.children, (dot, index) => (
<li
key={index}
onClick={() => {
Slide(DOT, index);
}}
>
{dot}
</li>
))}
</ul>
</Swipeable>
);
}
function reducer(state, { type, numItems }) {
switch (type) {
case "reset":
return initialState;
case PREV:
return {
...state,
dir: PREV,
sliding: true,
pos: state.pos === 0 ? numItems - 1 : state.pos - 1,
};
case NEXT:
return {
...state,
dir: NEXT,
sliding: true,
pos: state.pos === numItems - 1 ? 0 : state.pos 1,
};
case DOT:
if (state.pos > state.index) {
return {
...state,
dir: PREV,
sliding: true,
pos: state.index,
};
if (state.pos < state.index) {
return {
...state,
dir: NEXT,
sliding: true,
pos: state.index,
};
}
case "stopSliding":
return { ...state, sliding: false };
default:
return state;
}
}
export default Carousel;