2017-06-03 37 views
0

以下問題的最佳做法是什麼?React.Js:在執行onClick時防止同級事件的兄弟姐妹

我有一個父組件(局)和四個子組件(GameButton)這是一個可以點擊的按鈕。按鈕點擊照亮按鈕0.5秒,然後將按鈕轉回到初始樣式。我想在一個按鈕點亮時防止對其他按鈕的任何點擊。

class GameButton extends React.Component { 
    constructor(){ 
    super(); 
    this.state = { 
     illuminated:false, 
    }; 
    this.playButton = this.playButton.bind(this); 
    } 

    playButton(){ 

    if (this.props.gameActive && this.props.clickable){ 
     // lock all other buttons until this function is done executing 
     this.props.toggleButtonAccess(); 
     console.log(this.props.clickable); 

     // pass the second state update in a callback function to ensure delayed execution 
     this.setState({illuminated:true}, function() { 
     // arrow function to prevent binding of this to window 
     window.setTimeout(() => { 
     this.setState({illuminated: false}); 
     this.props.toggleButtonAccess(); 
     console.log(this.props.clickable); 

     },500); 
     }); 
    } 

    } 
    render() { 
    var buttonStyle = this.props.colorClass; 
    if (this.state.illuminated){ 
     buttonStyle += " illuminated-" + this.props.color; 
     console.log(buttonStyle); 
    } 
    return (
     <div className={buttonStyle} onClick={this.playButton}></div> 
    ); 
    } 
} 


class Board extends React.Component { 
    constructor(){ 
    super(); 
    this.state = { 
     gameActive:true, 
    }; 
    this.toggleButtonAccess = this.toggleButtonAccess.bind(this); 
    } 

    toggleButtonAccess(){ 
    this.clickable = (this.clickable) ? false : true; 
    } 

    render() { 
    return (
     <div className ="game-container"> 
     <GameButton colorClass="game-btn green" color="green" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn red" color="red" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn yellow" color="yellow" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn blue" color="blue" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 

     </div> 
    ); 
    } 
} 

到目前爲止,我設法由有父(局)組成的財產this.clickable,然後切換和關閉它每一個按鈕被點擊與toggleAccessButton()時間去做。但是,這不起作用。有一個更好的方法嗎?

+1

你應該讓'clickable'成爲父狀態的一部分。此外,'button' HTML元素具有'disabled'屬性,如果其中的表達式計算爲'true',則該屬性將被禁用。所以你的'GameButton'可以在渲染的''button'中有'disabled = {this.props.clickable}'。 – glhrmv

回答

1

有跡象表明,你需要改變一些東西。首先,在GameButton中,我看不到gameActive中的值。事實上,你不會爲這個道具傳遞任何價值。如果它沒有任何其他目的,您在這裏沒有提到,只需將其刪除即可。

class GameButton extends React.Component { 
    constructor(){ 
    super(); 
    this.state = { 
     illuminated:false, 
    }; 
    this.playButton = this.playButton.bind(this); 
    } 

    playButton(){ 

    if (this.props.clickable){ 
     // lock all other buttons until this function is done executing 
     this.props.toggleButtonAccess(); 
     console.log(this.props.clickable); 

     // pass the second state update in a callback function to ensure delayed execution 
     this.setState({illuminated:true}, function() { 
     // arrow function to prevent binding of this to window 
     window.setTimeout(() => { 
     this.setState({illuminated: false}); 
     this.props.toggleButtonAccess(); 
     console.log(this.props.clickable); 

     },500); 
     }); 
    } 

    } 
    render() { 
    var buttonStyle = this.props.colorClass; 
    if (this.state.illuminated){ 
     buttonStyle += " illuminated-" + this.props.color; 
     console.log(buttonStyle); 
    } 
    return (
     <div className={buttonStyle} onClick={this.playButton}></div> 
    ); 
    } 
} 

現在主板組件,你需要保持clickable在你的狀態和使用setState來改變它在toggleButtonAccess。這裏我也不明白你爲什麼在這個州有gameActive

class Board extends React.Component { 
    constructor(){ 
    super(); 
    this.state = { 
     gameActive:true, 
     clickable:true 
    }; 
    this.toggleButtonAccess = this.toggleButtonAccess.bind(this); 
    } 

    toggleButtonAccess(){ 
    this.setState({clickable:!this.state.clickable}); 
    } 

    render() { 
    return (
     <div className ="game-container"> 
     <GameButton colorClass="game-btn green" color="green" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn red" color="red" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn yellow" color="yellow" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn blue" color="blue" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     </div> 
    ); 
    } 
} 

假設你有正確設置其他的東西,現在應該按預期工作。

+0

對不起,創建MWE時我忘了刪除gameActive-state。 – miga89

1

我寧願使用React狀態。 在我的例子中,我切換cssClass。
下面的代碼示例:

const ButtonComponent = ({className,handler,idx}) => { 
    return (< div className = { 
     className 
    } > 
    < button onClick = { 
     handler 
    } > { 
     idx 
    } < /button> </div>); 
}; 

class HolderComponent extends React.Component { 
    constructor() { 
     super(); 
     this.state = { 
     current: null 
     } 

    } 

    handler(e, idx) { 
     e.preventDefault(); 
     console.log(idx + "CURRENT"); 
     this.setState({ 
     current: idx 
     },() => { 
     const self = this; 
     setTimeout(() => { 
      self.setState({ 
      current: null 
      }); 
     }, 1000) 
     }); 
    } 

    getButtons(props = []) { 

     return props.map((btn, idx) => this.getButton(idx)); 

    } 

    getButton(idx) { 

     return (< ButtonComponent key = { 
      idx + "uniqKey" 
      } 
      className = { 
      this.state.current === idx ? "test" : "testActive" 
      } 
      handler = { 
      (e) => this.handler(e, idx) 
      } 
      isActive = { 
      this.state.current === idx 
      } 
      idx = { 
      idx 
      } 
      />) 
     } 

     render() { 
      return (<div> { 
       this.getButtons([1, 2, 3, 4]) 
      } < /div>); 

      } 

     } 

     ReactDOM.render(< HolderComponent/> , document.getElementById("app"));