2017-08-30 58 views
0

我想實現的掃雷艇與之反應的孩子的狀態更新。我有其尺寸和炸彈的數量是可以改變的,因此應用程序組件狀態(sizeXsizeYbombNumber)將被更新頁眉部件(未示出),並且這些值將被向下發送到Table組分作爲道具。陣營基於父母的道具變化

我的問題是,Table組件狀態取決於App組件的道具當createTable()方法得到的道具更新調用它採用了更新的sizeXsizeY道具(這是很好的,當然),但由於某種原因它使用的bombNumber道具以前的值。

這是正確的做法嗎?如果是的話,我錯過了什麼?

class App extends Component { 
    constructor (props) { 
    super(props); 

    this.state = { 
    sizeX: DEFAULT_SIZE, 
    sizeY: DEFAULT_SIZE, 
    maxBombNumber: DEFAULT_BOMB_NUMBER, 
    bombNumber: DEFAULT_BOMB_NUMBER 

    } 

    updateSize (val, side) { 
    this.setState({[side]: val}, function() { 
     this.setState({maxBombNumber: this.calculateMaxBombNumber()}, function() { 
     if (this.state.maxBombNumber < this.state.bombNumber) { 
      this.setState({bombNumber: this.state.maxBombNumber}, function(){ 
      }); 
     } 
     }); 
    }); 
    } 

    render() { 
    return (
     <div className="App"> 
     <Table 
      sizeX={this.state.sizeX} 
      sizeY={this.state.sizeY} 
      bombNumber={this.state.bombNumber} 
     /> 
     </div> 
    ); 
    } 
} 

Table.js

class Table extends Component { 
    constructor (props) { 
    super(props); 

    this.state = { 
    table: this.createTable() 
    } 

    componentWillReceiveProps(nextProps) { 
    this.setState({table: this.createTable()}); 
    } 

    createTable() { 
    // function using sizeX, sizeY and bombNumber 
    } 
} 

更新:

如果我改變狀態控制檯日誌這裏打印出正確的價值觀,但孩子將使用舊值bombNumber

updateSize (val, side) { 
    this.setState({[side]: val}, function() { 
    this.setState({maxBombNumber: this.calculateMaxBombNumber()}, function() { 
     if (this.state.maxBombNumber < this.state.bombNumber) { 
     this.setState({bombNumber: this.state.maxBombNumber}, function(){ 
      console.log(this.state); 
     }); 
     } 
    }); 
    }); 
} 
+0

你確定這種情況下正確的工作,你如何期望? '如果(this.state.maxBombNumber chuve

+0

我這麼認爲,如果限制是'maxBombNumber',並且當前'bombNumber'大於那麼它應該減少。 –

+0

「,但由於某種原因,它使用bombNumber道具的先前值。「 - 如果沒有,你有prev的bombNumber值嗎?就是這樣嗎?對於誤解感到抱歉。 – chuve

回答

1

嘗試包所有來電的setState一:

updateSize(val, side) { 
    const maxBombNumber = this.calculateMaxBombNumber(); 
    const bombNumber = maxBombNumber < this.state.bombNumber ? maxBombNumber : this.state.bombNumber; 
    this.setState({ 
     [side]: val, 
     maxBombNumber, 
     bombNumber 
    }); 
} 

UPD:

componentWillReceiveProps(nextProps) { 
    this.setState({table: this.createTable()}); 
    } 

當表部件得到父應用新道具 - > componentWillReceiveProps執行和this.createTable( )方法使用之前的值不在nextProps中。以這種方式,您應該通過createTable的參數正確地給它。檢查這example

UPD 2:

這將是更好地使表部件 - 轉儲(無狀態的),只有在父組件應用程序中使用的狀態。只需將createTable方法移至應用程序,就足夠了。

或者你可以撥打CREATETABLE內呈現表的方法。

+0

我必須說我自己對這種行爲感到困惑,我只用一個'setState'調用了一個codepen,但它只能從第二個調用開始工作:https://codesandbox.io/s/2vqvkv4pon –

+0

用這段代碼行爲是一樣的 –

+0

我更新了原始代碼,我認爲問題在於''setState'不會馬上啓動,而是進入一個隊列,並且在將值發送給子代後實際設置的狀態會被設置爲 –

0

我相信你的問題是setState是一個異步調用,所以你使用的this.state沒有更新。有關將setState與函數一起使用的更多信息,請參閱此文章。 https://medium.freecodecamp.org/functional-setstate-is-the-future-of-react-374f30401b6b

我想這會得到你想要的東西:

updateSize(val, side) { 
    this.setState({ [side]: val }, function() { 
     this.setState({ maxBombNumber: this.calculateMaxBombNumber() }, this.setState(function (state) { 
      if (state.maxBombNumber < state.bombNumber) { 
       this.setState({ bombNumber: state.maxBombNumber }, function() { 
        console.log(state); 
       }); 
      } 
     })); 
    }); 
} 
+0

不工作。 :( –