状态属性正在更新,但浏览器未更新

时间:2020-03-16 04:06:22

标签: javascript reactjs react-redux

我有2个对象数组,其中包含不同的声音src url。我有2个div Q和W。两个div都与第一个对象数组相关联,我想在每次另一个div“ Toggle PadBank”时将它们与第二个数组相关联是onClicked的,因此单击它们时会产生不同的声音。

每次调用togglePadBank时,都会设置状态,以便buttonState指向第二个数组。我的控制台正在记录日志状态及其变化,但浏览器仍指向旧的对象数组。

这是我的代码笔:https://codepen.io/freeCodeCamp/pen/MJyNMd?editors=1010和 这是我的代码:

let bankOne = [{
  key:"Q",
  col:"blue",
  audioId: '1',
  url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_1.mp3'
}, {
  key:"W",
  col:"blue",
  audioId:'2',
  url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_2.mp3'
} ]

let bankTwo = [{
    key:"Q",
    col:'blue',
    audioId:'3',
    url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3'
  }, {
    key:"W",
    col:"blue",
    audioId:"4",
    url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-2.mp3'
  } ]




class Buttons extends React.Component{
  constructor(props){
    super(props)


  }


  render(){
    return(
    <div>
      <div style={{width:'100px', height:"100px", backgroundColor:this.props.color}} id={this.props.id} onClick={this.props.handleClick}><h3>{this.props.id} </h3></div>
        <audio id={this.props.audioId}>
        <source src={this.props.urlSource}/>
        </audio>
     </div>

    )
  }

}

class MyApp extends React.Component{
  constructor(props){
    super(props)
    this.state={
      buttonState:bankOne,
      padBankCol:"blue",
      currentPadBank:"bankOne"
    }
    this.handlesClick=this.handlesClick.bind(this)
    this.handleKeyDown=this.handleKeyDown.bind(this)
    this.playSound=this.playSound.bind(this)
    this.togglePadBank=this.togglePadBank.bind(this)
  }
  handlesClick(event){
    let indx=""
    let clickId=event.target.id
    let newState=Object.assign({},this.state)
    for(let i=0;i<this.state.buttonState.length;i++){
      if(this.state.buttonState[i].key===clickId){
        let soundId1=this.state.buttonState[i].audioId
        indx=i
        newState.buttonState[i].col="red"
        this.setState(
     newState  
    ) 
        this.playSound(soundId1)
        }
      }
     setTimeout(()=>{ 
       newState.buttonState[indx].col="blue"
       this.setState(
     newState  
    )
        },1000)


    }
  handleKeyDown(event){
    let indx=""
    let keyPress=String.fromCharCode(event.keyCode)
    console.log(keyPress)
    let newState=Object.assign({},this.state)
    for(let i=0;i<this.state.buttonState.length;i++){
      if(this.state.buttonState[i].key===keyPress){ 
        let soundId1=this.state.buttonState[i].audioId
        indx=i
        newState.buttonState[i].col="red"
       this.setState(
     newState  
    )
        this.playSound(soundId1)
        }

      }

    setTimeout(()=>{  
  newState.buttonState[indx].col="blue"
       this.setState(
     newState  
    )
        },1000)

  }


    playSound(id){
    let sound=document.getElementById(id)
    sound.play()
  }

  togglePadBank(){
    if(this.state.buttonState==bankOne){
      this.setState({
        buttonState:bankTwo,
        padBankCol:"red",
       currentPadBank:"bankTwo"
      })
    console.log(this.state.buttonState)
    } 
      else if(this.state.buttonState==bankTwo){
        this.setState({
          buttonState:bankOne,
        padBankCol:"blue",
       currentPadBank:"bankOne"
         } )
        console.log(this.state.buttonState)
      }   
  }




  render(){
    document.addEventListener("keydown",this.handleKeyDown)
    return(

    <div>
        <div style={{width:'400px',height:'400px', display:'flex',flexDirection:'row',backgroundColor:'green'}}>
        <Buttons id="Q" color= {this.state.buttonState[0].col} handleClick={this.handlesClick} urlSource={this.state.buttonState[0].url} audioId={this.state.buttonState[0].audioId}/>
          <Buttons id="W" color={this.state.buttonState[1].col} handleClick={this.handlesClick} audioId={this.state.buttonState[1].audioId} urlSource={this.state.buttonState[1].url} />
          <div style={{width:"100px",height:"50px",position:"relative",backgroundColor:this.state.padBankCol,left:"70px",top:"100px"}} onClick={this.togglePadBank}>Pad Bank Toggle</div>
        </div>



     </div>
    )
  }

}

ReactDOM.render(<MyApp />, document.getElementById('root'))

1 个答案:

答案 0 :(得分:1)

这确实很奇怪。在这一点上,代码真的很混乱,我无法指出它到底有什么问题。但是,您的情况有一种解决方法。

因此,当您单击div时,您可以创建一个,而不是始终使用音频标签。像这样

playSound(i){
    let doc = document.createElement('audio')
    doc.src = this.state.buttonState[i].url

    doc.play()
}

您需要传递匹配项的索引,而不是在playSound中传递ID。

这将起作用。但是很遗憾,我无法告诉您您的代码为什么不起作用。我强烈认为这是由于引用了您在代码中放入的对象。但是到目前为止,该代码实在太脏了,无法在有限的时间间隔内找出问题所在。

您可以采取以下措施来改进代码:

  1. 不变地更新状态。使用对象列表时要格外小心。由于制作浅表副本并不能保证不变性。
  2. 重用您的功能。例如,您的“ onClick”和“ onKeyPress”具有冗余代码。
  3. 请勿直接比较对象。像this.state.buttonState==bankOne一样会在这里引起麻烦。而是根据唯一键比较对象。

我希望能有所帮助。让我知道是否还有其他麻烦。