簡體   English   中英

如何對兩個不同的任務使用相同的 setState?

[英]How can I use the same setState for two different tasks?

編輯*** 代碼片段中的代碼並不意味着要運行,而只是顯示我的代碼,很抱歉造成混淆

我正在為電子商務應用程序工作 slider。 在我的 useState 數組上制作每個 slider map 以創建不同的卡片,並且 useState 正在從我獲取的 JSON 服務器接收數據。

現在我被困在一堵磚牆上,想知道如何使用相同的 state 來處理將圖像渲染到我的 slider 上並單擊箭頭以顯示新幻燈片。

在此處輸入圖像描述

我意識到我應該更新 state,但我覺得我已經(或沒有)考慮如何更新了。

我的代碼片段將顯示一個,我的代碼和兩個我的 JSON 服務器數據。

我收到“未捕獲的錯誤:重新渲染太多”。 React 限制渲染次數以防止無限循環

有人可以引導我完成我需要在這里做什么來完成這項任務嗎? 謝謝!

 import {useState, useEffect} from 'react'; import { ArrowLeftOutlined, ArrowRightOutlined } from "@material-ui/icons"; import styled from "styled-components"; import { set } from 'react-hook-form'; const Container = styled.div` width: 100%; height: 95vh; display: flex; // background-color: #b3f0ff; position: relative; overflow: hidden; `; const Arrow = styled.div` width: 50px; height: 50px; background-color: #e6ffff; border-radius: 50%; display: flex; align-items: center; justify-content: center; position: absolute; top: 0; bottom: 0; left: ${(props) => props.direction === "left" && "10px"}; right: ${(props) => props.direction === "right" && "10px"}; margin: auto; cursor: pointer; opacity: 0.5; z-index: 2; `; const Wrapper = styled.div` height: 100%; display: flex; transform: translateX(${props => props.slideIndx.data2 * -100}vw); ` const Slide = styled.div` width: 100vw; height: 100vw; display: flex; align-items: center; background-color: ${props => props.bg}; ` const ImgContainer = styled.div` height: 100%; flex:1; ` const Image = styled.img` padding-left: 30px; align-items: left; ` const InfoContainer = styled.div` height: 80%; flex:1; padding: 30px; ` const Title = styled.h1` font-size: 50px ` const Desc = styled.p` margin: 50px 0px; font-size: 20px; font-weight: 500; letter-spacing: 3px; ` const Button = styled.button` padding: 10px; font-size: 20px; background-color: transparent; cursor: pointer; ` const Slider = () => { const [slideIndx, setSlideIndx] = useState({data1:[], data2: 0}); const handleClick = (direction) => { if(direction === "left"){ setSlideIndx(slideIndx.data2 > 0? slideIndx.data2 - 1: 2); } else{ setArrowIndx(slideIndx.data2 < 2? slideIndx.data2 + 1: 0); } }; const newArray = [] setSlideIndx((slideIndx) => ({...slideIndx, data2: [...newArray] })); const fetchSliderItems = (id) => { fetch('http://localhost:3000/sliderItems').then(resp => resp.json()).then(data => { console.log(data) setSlideIndx(data) }) } useEffect(() => {fetchSliderItems()}, []) return ( <Container> <Arrow direction="left" onClick={() => handleClick("left")}> <ArrowLeftOutlined /> </Arrow> <Wrapper slideIndx={slideIndx.data2}> {slideIndx.data1.map((item) => ( <Slide bg={item.bg}> <ImgContainer> <Image src={item.img}/> </ImgContainer> <InfoContainer> <Title>{item.title}</Title> <Desc>{item.desc}</Desc> <Button>SHOP NOW</Button> </InfoContainer> </Slide> ))} </Wrapper> <Arrow direction="right" onClick={() => handleClick("right")}> <ArrowRightOutlined /> </Arrow> </Container> ) } export default Slider
 { "sliderItems": [ { "id": 1, "img": "../images/model1.png", "title": "SPRING CLEANING", "desc": "DONT MISS OUR BEST COLLECTION YET, USE #FLATIRON10 TO RECEIVE 10% OFF YOUR FIRST ORDER": "bg", "#b3ecff" }: { "id", 2: "img". "../images/model2,png": "title", "SHOW OFF HOW YOU DRESS": "desc", "WITH OUR HUGE SELECTION OF CLOTHES WE FIT ALL YOUR STYLING NEEDS": "bg", "#ccf2ff" }: { "id", 3: "img". "../images/model3,png": "title", "POPULAR DEALS": "desc", "RECEIVE FREE SHIPPING ON ALL ORDERS OVER $50:", "bg": "#fe6f9ff" } ] }

完全可以用一個 useState、兩個 useState 和我個人的偏好 useReducer 來做到這一點。

我只是舉個例子。 我沒有嘗試運行這段代碼,因為我沒有這些組件。 所以把它當作偽代碼來對待:

const initialState = {
  selectedIndex: 0,
  "sliderItems": [
    {
      "id": 1,
      "img": "../images/model1.png",
      "title": "SPRING CLEANING",
      "desc": "DONT MISS OUR BEST COLLECTION YET! USE #FLATIRON10 TO RECEIVE 10% OFF YOUR FIRST ORDER",
      "bg": "#b3ecff"
    },
    {
      "id": 2,
      "img": "../images/model2.png",
      "title": "SHOW OFF HOW YOU DRESS",
      "desc": "WITH OUR HUGE SELECTION OF CLOTHES WE FIT ALL YOUR STYLING NEEDS",
      "bg": "#ccf2ff"
    },
    {
      "id": 3,
      "img": "../images/model3.png",
      "title": "POPULAR DEALS",
      "desc": "RECEIVE FREE SHIPPING ON ALL ORDERS OVER $50!",
      "bg": "#fe6f9ff"
    },
  ],
}

function reducer(state, action) {
  switch (action.type) {
    case 'setData':
      return {
        selectedIndex: 0,
        sliderItems: action.sliderItems,
      };
    case 'slideRight':
      return {
        ...state,
        // this assumes you want to go back to index 0 if you slide right on last item
        selectedIndex: state.sliderItems.length - state.selectedIndex > 1 ? state.selectedIndex + 1 : 0,
      };
    case 'slideLeft':
      return {
        ...state,
        // this assumes you want to go to last item if sliding left on first item
        selectedIndex: state.selectedIndex === 0 ? state.sliderItems.length - 1 : state.selectedIndex - 1,
      };
    default:
      return state;
  }
}
const Example = () => {
  const [{ sliderItems, selectedIndex }, dispatch] = useReducer(initialState, reducer);

  return (
    <Container>
      <Arrow direction="left" onClick={() => dispatch({ type: 'slideLeft' })}>
        <ArrowLeftOutlined />
      </Arrow>
      <Wrapper slideIndx={selectedIndex}>
      {sliderItems.map((item) => (
        <Slide bg={item.bg}>
          <ImgContainer>
            <Image src={item.img}/>
          </ImgContainer>
          <InfoContainer>
            <Title>{item.title}</Title>
            <Desc>{item.desc}</Desc>
            <Button>SHOP NOW</Button>
          </InfoContainer>
        </Slide>
      ))}
      </Wrapper>
      <Arrow direction="right" onClick={() => dispatch({ type: 'slideRight' })}>
        <ArrowRightOutlined />
      </Arrow>
    </Container>
  )
}

如果您選擇嘗試這種方法,只需在您的獲取處理程序中分派一個 setData 操作。 這將用新項目重置 state 並從索引 0 開始。當然可以根據您的喜好修改行為。

dispatch({
  type: 'setData',
  sliderItems: fetchResult.sliderItems,
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM