2016-11-25 15 views
0

マップ関数を使用してオブジェクトの配列からゲームボードを作成し、クリック時にsetStateを呼び出してゲームを実行します。私はsuccessfuly状態を更新することができますが、私は別のアクションを実行するまで、ビューは更新されません。私は、マップ関数がどのように子要素(Cell)に小道具を渡すかに問題があると推測していますが、私が間違っていることを理解することはできません。reactjs - 状態を変更してもコンポーネントが再描画されない

var board = []; 
var width = 50; 
var height = 30; 
var size = width * height; 


for (var i=1; i<=size; i++) { 
    board[i] = {id: i, status: 'dead'}; 
} 

var Cell = React.createClass({ 
    turn: function() { 
    this.props.turn(this.props.id); 
    }, 

    render: function() { 
    return <div id={this.props.id} className={this.props.status} onClick={this.turn}></div> 
    } 
}); 

var GameBoard = React.createClass({ 
    getInitialState: function() {  
    return { 
     board: board 
    }; 
    }, 

    handleClick: function(id) { 
    var newBoard = this.state.board; 
    newBoard[id] = {id: id, status: 'alive'}; 
    this.setState({board: newBoard}); 
    }, 

    move: function() { 
    var board = this.state.board; 
    var newBoard = board; 
    for (var j=1;j<=board.length;j++) { 
     if (board[j].status == 'alive') { 
     newBoard[j-1] = {id: j-1, status: 'alive'}; 
     newBoard[j] = {id: j, status: 'dead'}; 
     } 
    } 
    this.setState({board: newBoard}); 
    }, 

    render: function() { 
    var squares = this.state.board.map(function(item){ 
     return <Cell id={item.id} status={item.status} turn={this.handleClick}/> 
    }.bind(this)); 
    return (
     <div> 
     <h1>Game of Life</h1> 
     <button className="btn btn-default" onClick={this.move}>Run</button> 
     <div className='boardContainer'>{squares}</div> 
     </div> 
    ); 
    } 
}); 

ReactDOM.render(<GameBoard/>,document.getElementById('app'));  

http://codepen.io/Theeeus/pen/YpQzPO?editors=0010

答えて

0

あなたmove関数内のループはオフずつなので、setStateとのラインに到達する前にエラーがスローされます。メソッドの最初の2行は、変数newBoardthis.state.boardへの参照を代入するだけです。したがって、状態を「更新」していますが、正しくはsetStateではありません。そのため、次回のクリックでボードが更新されます。setStateを​​に呼び出します。

1)

var board = this.state.board; 
var newBoard = board; // Note, this is a reference to this.state.board. That's bad! 
for (var j=1; j<=board.length - 1; j++) { // note, -1 
    ... 
} 
+0

Thanks Sam!ループを変更すると、すでにエラーが修正されていますが、状態に変数を割り当てることによっても状態に影響を与えることは考えられませんでした。私は将来的に問題を避けるためにその部分を修正するつもりです。 –

0

を使用してくださいあなたが代わりに状態そのもの

2)ループのためにオフ・バイ・ワンエラーを修正する状態のディープコピーを変更する必要があります

if(var i = 0;i < arr.length;i++) 

、代わりの

if(var i = 1;i<=arr.length;i++){} 

あなたの質問では、あなたの移動関数のjがboard.lengthに等しいとき、それはエラーになります。 コード内の2つのifサイクルを変更します。 私が助けることを願っています。

var board = []; 
 
var width = 2; 
 
var height = 3; 
 
var size = width * height; 
 

 

 
for (var i=0; i < size; i++) { 
 
    board[i] = {id: i, status: 'dead'}; 
 
} 
 

 
var Cell = React.createClass({ 
 
    turn: function() { 
 
    this.props.turn(this.props.id); 
 
    }, 
 

 
    render: function() { 
 
    return <div id={this.props.id} className={this.props.status} onClick={this.turn}></div> 
 
    } 
 
}); 
 
var GameBoard = React.createClass({ 
 
    getInitialState: function() {  
 
    return { 
 
     board: board 
 
    }; 
 
    }, 
 

 
    handleClick: function(id) { 
 
    var newBoard = this.state.board; 
 
    newBoard[id] = {id: id, status: 'alive'}; 
 
    this.setState({board: newBoard}); 
 
    }, 
 

 
    move: function() { 
 
    var board = this.state.board; 
 
    var newBoard = board; 
 
    for (var j=0;j < board.length;j++) { 
 
     if (board[j].status == 'alive') { 
 
     newBoard[j-1] = {id: j-1, status: 'alive'}; 
 
     newBoard[j] = {id: j, status: 'dead'}; 
 
     } 
 
    } 
 
    this.setState({board: newBoard}); 
 
    }, 
 

 
    render: function() { 
 
    var squares = this.state.board.map(function(item){ 
 
     return <Cell key = {item.id} fuck={item.id} id={item.id} status={item.status} turn={this.handleClick}/> 
 
    }.bind(this)); 
 

 
    return (
 
     <div> 
 
     <h1>Game of Life</h1> 
 
     <button className="btn btn-default" onClick={this.move}>Run</button> 
 
     <div className='boardContainer'>{squares}</div> 
 
     </div> 
 
    ); 
 
    } 
 
}); 
 

 
ReactDOM.render(<GameBoard/>,document.getElementById('app'));
.dead{ 
 

 
width:10px;height:10px;border:1px solid red;margin:3px; 
 

 
     } 
 
     .alive{ 
 
     border:1px solid green;margin:3px;width:10px;height:10px; 
 
     }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="app"></div>

0

あなたはthis.stateを変異しています。 React docsは、これがno-noであることを指定します。

handleClick: function(id) { 
    this.setState({ 
    ...this.state, 
    board: [ 
     ...this.state.board.slice(0, id), 
     { 
     id, 
     status: 'alive' 
     }, 
     ...this.state.board.slice(id + 1) 
    ] 
    }); 
}, 

move: function() { 
    this.setState({ 
    ...this.state, 
    board: this.state.board.map((place, id, board) => { 
     const nextPlace = board[id + 1]; 
     if (nextPlace.status === 'alive') { 
     return { 
      ...place, 
      status: 'alive' 
     }; 
     } else if (place.status === 'alive') { 
     return { 
      ...place, 
      status: 'dead' 
     }; 
     } 
     return place; 
    }) 
    }); 
}, 

注:これらの機能は、いくつかの新しいJavascriptの拡散演算子(...place)などの機能と矢印機能を使用GameBoard部品の内部では、私はもっとこのように見えるためにあなたのhandleClick()move()機能を書き換えると思います。このコードを実行しようとすると、これらの機能によって構文エラーが発生する可能性があります。

+0

私は普及している演算子に慣れていませんが、私はドキュメントを読んで試してみます。ありがとう! –

関連する問題