2017-06-29 12 views
0

jsに反応するのは初めてで、簡単なマジックスクエアゲームを構築しようとしています。私は初期値を設定することができます。私は親コンポーネントに反映させるためにユーザー入力を得る方法を考え出すのに悩まされています。すなわち、ボードクラスのhandleChange(i)メソッドの空のSquareに入力された新しい値をsquares [i]に設定します。反応onChangeバインド値を親の配列

class Square extends React.Component { 

    render() 
    { 
    return (
     <input type="text" className="square" value={this.props.value} onChange={this.handleChange}> 
     </input> 
    ); 
    } 
} 

/* Defines the Main Game Board */ 
class Board extends React.Component { 
    constructor(props) { 
    super(props); 

    this.handleChange = this.handleChange.bind(this); 

    /*Array to store Random numbers*/ 
    const randArray = []; 

    for(var i = 0; i < 3; i++) 
    { 
     var numberIsInArray = false; 
     var rand = generateRandomNumb(1, 9); 
     for(var j = 0; j < randArray.length; j++){ 
      if(rand === randArray[j]) { 
       numberIsInArray = true; 
       i--; 
      } 
     } 
     if(!numberIsInArray){ 
     randArray.push(rand); 
     } 
    } 

    /*function to generate Random Numbers*/ 
    function generateRandomNumb(min, max) 
    { 
     return Math.floor(Math.random() * (max - min) + min); 
    } 

    function check(grid_val, arr) 
    { 
     if (arr[0] === grid_val || arr[1] === grid_val || arr[2] === grid_val) 
     return grid_val; 
    } 

    this.state = { 
     squares: Array(
     (4,check(4,randArray)) 
     ,(9,check(9,randArray)) 
     ,(2,check(2,randArray)) 
     ,(3,check(3,randArray)) 
     ,(5,check(5,randArray)) 
     ,(7,check(7,randArray)) 
     ,(8,check(8,randArray)) 
     ,(1,check(1,randArray)) 
     ,(6,check(6,randArray)) 
     ) 
    }; 
    } 

    handleChange(i) { 
    const squares = this.state.squares.slice(); 
    squares[i] = ''; 
    //this.setState({squares: squares}); 
    } 

    renderSquare(i) { 
    return (
     <Square 
     value={this.state.squares[i]} 
     onChange={this.handleChange(i)} 
     /> 
    ); 
    } 

    render() { 

    const status = this.state.squares;  

    return (
     <div> 
     <div className="App-header"> 
      <img src={logo} className="App-logo" alt="logo" /> 
      <h2>Sudoku React</h2> 
     </div> 
     <div className="status">{status}</div> 
     <div className="board-row"> 
      {this.renderSquare(0)} 
      {this.renderSquare(1)} 
      {this.renderSquare(2)} 
     </div> 
     <div className="board-row"> 
      {this.renderSquare(3)} 
      {this.renderSquare(4)} 
      {this.renderSquare(5)} 
     </div> 
     <div className="board-row"> 
      {this.renderSquare(6)} 
      {this.renderSquare(7)} 
      {this.renderSquare(8)} 
     </div> 
     <div> 
      <button onClick={() => window.location.reload()}>Start New Game</button> 
     </div> 
     </div> 
    ); 
    } 
} 
export default Board; 

答えて

0

ここにいくつかの問題があります。

問題1

あなたがvalueonChangeという名前の小道具を渡している<Square />コンポーネントを作成します。しかし、Squareコンポーネントでは、をonChangeハンドラとして使用しようとしています。

this.handleChangeSquareのプロパティとして存在します。代わりに、Board親によって渡されたthis.props.onChangeを使用する必要があります。

class Square extends React.Component { 
    // handleChange() { 
    // this is the none existant function referred to in the render function 
    // Instead: use this.props.onChange passed by the parent <Board /> 
    // } 

    render() 
    { 
    return (
     <input type="text" className="square" value={this.props.value} onChange={this.handleChange}> 
     </input> 
    ); 
    } 
} 

これはまだ原因

号2

...に、しかし動作しません入力のonChange方法は、関数であることが予想されます。問題#1は固定で

、スクエアのthis.props.onChangeundefinedだろう。 handleChangeがpropとして渡すときに呼び出されている(呼び出されている)ためです。 handleChangeには戻り値がないため、undefinedを渡します。

renderSquare(i) { 
    return (
    <Square 
     value={this.state.squares[i]} 
     onChange={this.handleChange(i)} // handleChange is being invoked! Note() 
    /> 
); 
} 

この問題を解決するための最低限の編集の必要性は、私たちは私たちの状態を更新するために使用する、イベントを受け入れる機能を、返すhandleChange持つことです。

handleChange (i) { 
    // Return ES6 bound function to maintain `this` 
    return (e) => { 
    const squares = this.state.squares.slice(); 
    squares[i] = e.target.value; // The value of the input 
    this.setState({squares: squares}); 
    }; 
} 

p.s.追加の一般的なコメント renderSquarehandleChange

this.renderSquare = this.renderSquare.bind(this); 
this.handleChange = this.handleChange.bind(this); 

あるようなコンストラクタでthisにバインドする必要があり、私も<Board />のコンストラクタのうち、generateRandomNumbcheckを移動し、任意のclassの外で、非常にあなたのコード例を一番上にそれらを配置します。

あまりにも機能にrandArray世代を移動し、また、上部に移動します。

function generateRandArray() { 
    var randArray = []; 
    for(var i = 0; i < 3; i++) 
    { 
    var numberIsInArray = false; 
    var rand = generateRandomNumb(1, 9); 
    for(var j = 0; j < randArray.length; j++){ 
     if(rand === randArray[j]) { 
     numberIsInArray = true; 
     i--; 
     } 
    } 
    if(!numberIsInArray){ 
     randArray.push(rand); 
    } 
    } 
    return randArray; 
} 

そして<Board />

const randArray = generateRandArray();  
のコンストラクタで
関連する問題