如何在可重用组件中分隔状态

时间:2019-05-11 01:04:04

标签: javascript reactjs

编辑:我已经尝试为每个实现使用this.props.id来个性化每个组件实现的状态。因此,我的目标是确保每次点击都能分别影响每个实现,而不是所有实现,但是这种方法似乎失败了。

我有一个可重复使用的滑块组件,

在react组件中,我正在使用其中几个滑块的util

我希望当我单击这些滑块之一时,只有其中一个会移动,但它们都会向左或向右移动。

当前,当我单击其中一个组件的左_右按钮时,所有这些组件都会移动,那么如何使只有我单击的那个组件移动?

此处是沙箱https://codesandbox.io/s/kkqy360p73

请问如何区分可重用组件的状态?

这是我导入状态的方式:

import FruitSlideUtil from "~/lib/pizza/FoodSlideUtil/FoodSlideUtil"
import BeverageSlideUtil from "~/lib/pizza/FoodSlideUtil/FoodSlideUtil"
import DessertSlideUtil from "~/lib/pizza/FoodSlideUtil/FoodSlideUtil"

这是我通常在父组件中实现的方式:

<div 
    className={style.slide_container} 
    ref="slideContainer" 
>              
    <div 
        className={style.option_item_container}
    >
        <FruitSlideUtil
            ref="FoodSlideUtil"
            state={fruitSlideState}
            scopeProps={this.state.scopeProps}
            itemSelected={fruitStock}
            optFood={null}
        />
    </div>                                       
</div>

这是我可重用组件的状态:

state={
    // scopeProps: this.props.scopeProps,
    ["scopeProps"+this.props.id]: 5,
    // number of items in he slider
    ["totalSliderItem" +this.props.id]:0,
    ["distance"+ this.props.id]:0, // distance between two elements in px
    ["currentPosition"+this.props.id]:0, // current position
    ["updatedTotal" + this.props.id]:0, // total number of elements after adding remaining elements,

    // element remaining outside foodScopeView
    ["remainOutsideLeft" +this.props.id]:0,
    ["remainOutsideRight"+this.props.id]:0
  } 

此处是处理可重用组件中的移动的函数:

 componentDidMount(){
    // set CSS variable 
    // § call body variable     
    let root= document.body;

    // § update css variable CSS variable --unit-width
    // call metacontainer ref
    let SliderMetaContainer= this.refs.sliderMetaContainer
    // get metacontainer width
    let metaContainerWidth=SliderMetaContainer.getBoundingClientRect().width
    let unitWidth= metaContainerWidth/this.state["scopeProps" +this.props.id]
    root.style.setProperty('--unit-width', unitWidth + "px") ;

    // set number of items contained in slider
    let sliderContainer= this.refs.sliderContainer 
    let sliderContainerLength= sliderContainer.childElementCount
    let updatedTotal=sliderContainerLength;
    console.log("updatedTotal, this.state.scopeProps: ", updatedTotal, this.state["scopeProps" +this.props.id])

    console.log("initialOutsideRight: ", initialOutsideRight)
    console.log("distance: ", distance)
    let initialOutsideRight= updatedTotal - this.state["scopeProps" +this.props.id]


    // get the bounding rectangles
    var div1rect = sliderContainer.children[0].getBoundingClientRect();
    var div2rect = sliderContainer.children[1].getBoundingClientRect();

    // get div1's center point
    var div1x = div1rect.left + div1rect.width/2;
    var div1y = div1rect.top + div1rect.height/2;

    // get div2's center point
    var div2x = div2rect.left + div2rect.width/2;
    var div2y = div2rect.top + div2rect.height/2;

    // calculate the distance using the Pythagorean Theorem (a^2 + b^2 = c^2)
    var distanceSquared = Math.pow(div1x - div2x, 2) + Math.pow(div1y - div2y, 2);
    var distance = Math.sqrt(distanceSquared);


    // initialize state after componentDidMount
    this.setState({
      ["totalSliderItem" + this.props.id]:sliderContainerLength,
      ["remainOutsideRight" +this.props.id]: initialOutsideRight,
      ["distance" + this.props.id]:distance,
      ["updatedTotal" +this.props.id]:updatedTotal
    });    
  }



  // when user click a button to move => handleSlideMove()
  handleSlideMove=(direction)=>{
    let cP;
    // go right
    if(direction === 'right'){
      console.log("go toward right")
      cP = this.state["currentPosition" +this.props.id] +  this.state["scopeProps" +this.props.id];
      console.log("cP: ", cP)
      if(cP == this.state["updatedTotal" + this.props.id]){
        // this.state.currentPosition = 0 ;
        this.setState( currentState => ({
          ["currentPosition" + this.props.id]:0,
          ["remainOutsideLeft" +this.props.id]:0,
          ["remainOutsideRight" +this.props.id]:currentState["updatedTotal" + this.props.id] - currentState["scopeProps"+this.props.id],

        }), () => { 
          document.body.style.setProperty('--item-left-food', 0 + "px");
        });

      }else{

        if(this.state["remainOutsideRight"+ this.props.id] < this.state["scopeProps" +this.props.id]){
          cP=this.state["currentPosition" +this.props.id] + this.state["remainOutsideRight" + this.props.id]
          this.setState( currentState =>({
            ["currentPosition" +this.props.id]:cP,
            ["remainOutsideLeft" +this.props.id]:currentState["remainOutsideLeft"+this.props.id] + currentState["remainOutsideRight"+this.props.id],
            // all remain outside right will be used 
            ["remainOutsideRight"+ this.props.id]:currentState["remainOutsideRight" +this.props.id]-  currentState["remainOutsideRight"+this.props.id],
          }), () => {
            document.body.style.setProperty('--item-left-food', -cP*this.state["distance" +this.props.id] + "px"); 
          });   
        }
        else{
          this.setState(currentState =>({
            ["currentPosition" +this.props.id]:cP,
            ["remainOutsideLeft"+this.props.id]:currentState["remainOutsideLeft"+this.props.id] + currentState["scopeProps"+this.props.id],
            // all remain outside right will be used 
            ["remainOutsideRight" + this.props.id]:currentState["remainOutsideRight"+this.props.id] - currentState["scopeProps"+this.props.id],
          }), () => {
            document.body.style.setProperty('--item-left-food', -cP*this.state["distance" + this.props.id] + "px"); 
          });        
        }
      }
    }
    // go left
    else{
      console.log("go toward left")
      cP = this.state["currentPosition" +this.props.id] -  this.state["scopeProps" + this.props.id];
      console.log("this.state.currentPosition,  this.state.scopeProps: ",this.state["currentPosition" +this.props.id],  this.state["scopeProps" +this.props.id])
      console.log("this.state.currentPosition -  this.state.scopeProps: ", this.state["currentPosition" +this.props.id] -  this.state["scopeProps" + this.props.id])
      if(this.state["currentPosition" + this.props.id] == 0){
        console.log("this.state.currentPosition == 0: ")

        // this.state.currentPosition = this.state.updatedTotal - scopeProps;
        this.setState(currentState =>({
            ["currentPosition" +this.props.id]:currentState["updatedTotal"+this.props.id] - currentState["scopeProps"+this.props.id],
            ["remainOutsideLeft"+this.props.id]:currentState["updatedTotal"+this.props.id] - currentState["scopeProps"+this.props.id],
            ["remainOutsideRight"+this.props.id]:0
          }), 
        () => {
         document.body.style.setProperty('--item-left-food', - this.state["currentPosition"+this.props.id]*this.state["distance"+this.props.id] + "px");
        })

      }else{ 
        console.log("this.state.currentPosition differ than 0")
        console.log(
          "this.state.remainOutsideLeft, this.state.scopeProps: ",
          this.state["remainOutsideLeft"+this.props.id], this.state["scopeProps"+this.props.id]
        )
        console.log("this.state.remainOutsideleft < this.state.scopeProps: ", this.state["remainOutsideleft"+this.props.id] < this.state["scopeProps"+ this.props.id])
        if(this.state["remainOutsideLeft" + this.props.id] < this.state["scopeProps" +this.props.id]){
          console.log("differ than 0 remain inferior than scope: ")
          cP=this.state["currentPosition"+this.props.id] - this.state["remainOutsideLeft"+this.props.id]
          this.setState(currentState =>({
            ["currentPosition"+this.props.id]:cP,
            ["remainOutsideLeft" +this.props.id]:currentState["remainOutsideLeft"+this.props.id] - currentState["remainOutsideLeft"+this.props.id],
            ["remainOutsideRight" +this.props.id]:currentState["remainOutsideRight"+this.props.id] + currentState["remainOutsideLeft"+this.props.id]
          }), () => {
            document.body.style.setProperty('--item-left-food', -cP*this.state["distance" +this.props.id] + "px"); 
          });   
        }
        else{
          console.log("differ than 0 remain superior to scope: ")
          this.setState(currentState =>({
            ["currentPosition"+this.props.id]:cP,
            ["remainOutsideLeft"+this.props.id]:currentState["remainOutsideLeft"+this.props.id] - currentState["scopeProps"+this.props.id],
            ["remainOutsideRight" +this.props.id]:currentState["remainOutsideRight" +this.props.id] + currentState["scopeProps"+this.props.id]
          }), () => {
            document.body.style.setProperty('--item-left-food', -cP*this.state["distance"+this.props.id] + "px"); 
          });        
        }    
        // this.setState(currentState => ({currentPosition:cP}), () => {
        //  document.body.style.setProperty('--item-left', -cP*this.state.distance + "px")       
      }
    }
  }

1 个答案:

答案 0 :(得分:2)

所以这里有很多问题。该代码非常冗长且难以理解,并且您没有利用React提供的功能(顺便说一句,我从未见过旋转传送带中使用的勾股定理!)。为了回答您的问题,控件影响所有滑块的原因是因为您使用CSS属性控制控件的位置,而CSS属性是通过在左右函数中添加到正文中的:

document.body.style.setProperty('--item-left-food', -cP*this.state["distance" +this.props.id] + "px"); 

使用React时,除非绝对必要,否则要避免手动操作DOM(或使用引用),应使用JSX返回的 inside 滑块组件根据其内部条件有条件地添加任何类或样式州。您将在父组件中声明3个状态相同的实例作为从未使用过的状态道具,并将3个不同名称的滑块组件导入不同的时间。您只应导入一次,传递需要更改的道具,并在组件本身内部设置默认状态或道具。

{{3}}是有关使用React构建滑块组件的文章。