使用 redux/toolkit 进行组件间的状态切片

Using redux / toolkit for state slicing between components

我的 SlideShow with Redux 遇到了问题,我是新手。我试图找出连接下拉列表 select 和下一个和上一个按钮的逻辑,以便 redux 跟踪我的状态。 我希望用户能够浏览幻灯片,还能够 select 从下拉列表中选择一张幻灯片。我无法弄清楚我应该做些什么来连接这一切,但我想我很接近......:\

我的幻灯片

const SlideData = [
  {
    title: "Introduction",
    content: "This is some content",
  },
  {
    title: "Slide 2",
    content: "This is some content",
  },
  {
    title: "Slide 3",
    content: "This is some content",
  },
  {
    title: "Slide 4",
    content: "This is some content",
  },
];

export default SlideData;

REDUX 文件

import { createSlice, configureStore } from "@reduxjs/toolkit";
import SlideData from "../SlideData";

//SET INITIAL STATE//
const initialSlideState = {
  SlideData,
  totalSlides: SlideData.length,
  currentSlide: 0,
  progress: 0,
};

//SET REDUCERS//
const slideSlice = createSlice({
  name: "slide",
  initialState: initialSlideState,
  reducers: {
    setCurrentSlide(state, action) {
      state.currentSlide = SlideData[action.payload];
    },
    nextSlide(state) {
      if (state.currentSlide < state.totalSlides) {
        state.currentSlide++;
      }
    },
    prevSlide(state) {
      if (state.currentSlide > 0) {
        state.currentSlide--;
      }
    },
    setProgress(state, action) {
      state.progress = action.payload;
    },
  },
});

//CREATE STORE//
const store = configureStore({
  reducer: slideSlice.reducer,
});

export const slideActions = slideSlice.actions;
export default store;

幻灯片文件

//IMPORTS//
import React, { useRef } from "react";
import styles from "./Slideshow.module.css";
import Button from "./UI/Button";
import { Slide } from "react-slideshow-image";
import SlideData from "../SlideData";
import { useSelector, useDispatch } from "react-redux";
import { slideActions } from "../store/index";
import "react-slideshow-image/dist/styles.css";


export default function Slideshow() {
  const dispatch = useDispatch();
  const slideRef = useRef();
  const currentSlide = useSelector((state) => state.currentSlide);
  const totalSlides = useSelector((state) => state.totalSlides);

  //SET CURRENT SLIDE
  const setCurrentSlideHandler = (index) => {
    dispatch(slideActions.setCurrentSlide(index));
  };

  //NEXT SLIDE
  const nextSlideHandler = () => {
    dispatch(slideActions.nextSlide());
    dispatch(slideActions.setProgress((currentSlide / totalSlides) * 100));
    slideRef.current.goNext();
  };

 //PREVIOUS SLIDE
  const prevSlideHandler = () => {
    dispatch(slideActions.prevSlide());
    dispatch(slideActions.setProgress((currentSlide / totalSlides) * 100));
    slideRef.current.goBack();
  };

//GO TO SLIDE (DROPDOWN)<<--feel like i'm close here? 
  const goto = ({ target }) => {
    console.log("Before: " + currentSlide);
    let info = parseInt(target.value, 10);
    console.log(info);
    setCurrentSlideHandler(info);
    slideRef.current.goTo(currentSlide);
    console.log("after: " + currentSlide);
  };

  //SLIDESHOW PROPS//
  const properties = {
    transitionDuration: 200,
    autoplay: false,
    arrows: false,
  };

  //MAP DATA FOR DROPDOWN//
  const options = SlideData.map((item, index) => (
    <option key={index} value={index}>
      {item.title}
    </option>
  ));

  return (
    <div className={styles.container}>
      <Slide ref={slideRef} {...properties}>
        {SlideData.map((item, index) => (
          <div key={index} className={styles.slide}>
            <h2>{item.title}</h2>
            <p>{item.content}</p>
          </div>
        ))}
      </Slide>
      <div>
        <Button type="button" onClick={prevSlideHandler}>
          Back
        </Button>
        <Button type="button" onClick={nextSlideHandler}>
          Next
        </Button>
        <select className={styles.select} onChange={goto}>
          <option>--Select--</option>
          {options}
        </select>
      </div>
    </div>
  );
}

预览

我认为问题在于,在您的组件中,您既使用库提供的方法,又尝试基于 redux 状态来做事。如果您尝试仅使用 redux 设置幻灯片,那么您想要的是,在按下箭头前进或后退时,将(新的)“currentSlide”(索引)分派给 redux,然后使用 useEffect(()) 来监听 currentSlide 选择器的变化。当值发生变化时,您将使用更新后的值通过新索引调用 the libraries method goTo(index)

那看起来像: (免责声明:我正在删除与我要表达的观点无关的内容)

切片

import { createSlice, configureStore } from "@reduxjs/toolkit";
import SlideData from "../SlideData";

//SET INITIAL STATE//
const initialSlideState = {
  SlideData,
  totalSlides: SlideData.length,
  currentSlide: 0,
};

//SET REDUCERS//
const slideSlice = createSlice({
  name: "slide",
  initialState: initialSlideState,
  reducers: {
    setCurrentSlide(state, action) {
      state.currentSlide = action.payload;
    },
    nextSlide(state) {
      if (state.currentSlide < state.totalSlides) {
        state.currentSlide++;
      }
    },
    prevSlide(state) {
      if (state.currentSlide > 0) {
        state.currentSlide--;
      }
    },
  },
});

组件

//IMPORTS//
import React, { useRef } from "react";
import styles from "./Slideshow.module.css";
import Button from "./UI/Button";
import { Slide } from "react-slideshow-image";
import SlideData from "../SlideData";
import { useSelector, useDispatch } from "react-redux";
import { slideActions } from "../store/index";
import "react-slideshow-image/dist/styles.css";


export default function Slideshow() {
  const dispatch = useDispatch();
  const slideRef = useRef();
  const currentSlide = useSelector((state) => state.currentSlide);
  const totalSlides = useSelector((state) => state.totalSlides);

  useEffect(() => {
    slideRef.current.goTo(currentSlide)
  }, currentSlide)

  //SET CURRENT SLIDE
  const setCurrentSlideHandler = (index) => {
    dispatch(slideActions.setCurrentSlide(index));
  };

  //NEXT SLIDE
  const nextSlideHandler = () => {
    dispatch(slideActions.nextSlide());
  };

  //PREVIOUS SLIDE
  const prevSlideHandler = () => {
    dispatch(slideActions.prevSlide());
  };

  //GO TO SLIDE (DROPDOWN)<<--feel like i'm close here? 
  const goto = ({ target }) => {
    let info = parseInt(target.value, 10);
    setCurrentSlideHandler(info);
  };

  //SLIDESHOW PROPS//
  const properties = {
    transitionDuration: 200,
    autoplay: false,
    arrows: false,
  };

  //MAP DATA FOR DROPDOWN//
  const options = SlideData.map((item, index) => (
    <option key={index} value={index}>
      {item.title}
    </option>
  ));

  return (
    <div className={styles.container}>
      <Slide ref={slideRef} {...properties}>
        {SlideData.map((item, index) => (
          <div key={index} className={styles.slide}>
            <h2>{item.title}</h2>
            <p>{item.content}</p>
          </div>
        ))}
      </Slide>
      <div>
        <Button type="button" onClick={prevSlideHandler}>
          Back
        </Button>
        <Button type="button" onClick={nextSlideHandler}>
          Next
        </Button>
        <select className={styles.select} onChange={goto}>
          <option>--Select--</option>
          {options}
        </select>
      </div>
    </div>
  );
}

根据以上内容,无论您选择哪种方式(前进、后退或明确选择),都会调度适当的操作,并在您所在的状态中更新 currentSlide (INDEX)获取您的选择器值。当组件发现选择器值已更改时,它将使用该值调用库的 goTo(index) 方法。