简体   繁体   English

在对象中将对象绑定为组件状态键值的正确方法

[英]correct way to bind an object as value of a component's state key in react

I'm creating a minesweeper React app and inside the Board stateful component I've initialized and populated the board with mines and other information. 我正在创建一个minesweeper React应用,并在板有状态的组件内部进行了初始化,并使用地雷和其他信息填充了板。

The initialization of this board is made as follows 该板的初始化如下

// Method that creates a board of empty tiles, populates it with mines and gets the number of neighbouring
// mines for every tile on the board. Returns the initialized board  
initializeBoard(height, width, mines){
    const emptyTiles = this.createEmptyArray(height, width);
    const populatedTiles = this.populateBoard(emptyTiles, height, width, mines);
    const neighbourTiles = this.getNumOfMinesNeighbours(populatedTiles,height, width);
    return this.renderBoard(neighbourTiles);
   }

renderBoard returns a JSX component. renderBoard返回一个JSX组件。

I receive height, width and mines as props passed from another component. 我从另一个组件传递来的道具收到高度,宽度和地雷。

My Board status looks like this: 我的董事会状态如下:

state = {
    mineCount: this.props.mines,
    gameStatus: null,
    boardData: null
}

And I want to dynamically render the initialized board and update Board's state value for boardData key. 我想动态呈现初始化的板并更新boardData键的Board状态值。 Now, I've arrived two different approaches for this: 现在,我到达了两种不同的方法:

  1. dynamically call initialize board() in Board's render() method, and update its state somehow 在Board的render()方法中动态调用Initialize board(),并以某种方式更新其状态
  2. Directly assign the state boardData value with a call to initializeBoard() 通过调用initializeBoard()直接分配状态boardData值

Approach #1 would look like this, inside render(): 方法1在render()中看起来像这样:

render() {  
    const board= this.initializeBoard(this.props.height, this.props.width, this.props.mines);
    //Save state throws Maximum update depth exceeded.
    return (
        <div>
            {board}
        </div> ...} //end of render

Approach #2: 方法2:

state = {
    mineCount: this.props.mines,
    gameStatus: null,
    boardData: this.initializeBoard(this.props.height, this.props.width, this.props.mineCount)
}

Now, I know that setting the state of the component inside render() is a no-no , but also I am unable to find a proper lifecycle hook that will work when an object is created prior to render() and then dynamically rendered into JSX, since I'm not receiving this object via props. 现在,我知道在render()中设置组件的状态是不行 ,但我也找不到合适的生命周期挂钩 ,当在render()之前创建对象然后将其动态渲染到对象时,该挂钩将起作用JSX,因为我没有通过道具接收此对象。

So What I want to know is this : 所以我想知道的是

  • Is the approach #2 a good/appropriate one? 方法2是好的/适当的方法吗? Or is calling a method to store a state's key value a bad practice? 还是调用存储状态键值的方法是一种不好的做法?
  • Is there something I'm missing when it comes to lifecycle hooks and objects created prior to render()? 关于生命周期挂钩和在render()之前创建的对象,我是否缺少某些东西?
  • Is there any 'best practice' to store a state's key value in this situation? 在这种情况下,是否有任何“最佳实践”来存储国家的关键值?

Is the approach #2 a good/appropriate one? 方法2是好的/适当的方法吗? Or is calling a method to store a state's key value a bad practice? 还是调用存储状态键值的方法是一种不好的做法?

No, why should it? 不,为什么要这样?

Is there something I'm missing when it comes to lifecycle hooks and objects created prior to render()? 关于生命周期挂钩和在render()之前创建的对象,我是否缺少某些东西?

No. there is no valid reason to hook in there. 不,没有正当理由要钩在那里。

Is there any 'best practice' to store a state's key value in this situation? 在这种情况下,是否有任何“最佳实践”来存储国家的关键值?

yes, #2. 是的,#2。

Maybe more comments in the code will help me to better understand the problem. 也许代码中的更多注释将帮助我更好地理解问题。

constructor(super) {
   state = {
     mineCount: this.props.mines,
     gameStatus: null,
     boardData: null
   }
   this.board = null
   this.populatedTiles = null;
   this.neighbourTiles = null; 
   this.width = this.props.width;
   this.height = this.props.height; 
}

componentDidMount() {
   this.initializeBoard(this.height, this.width, this.state.mines);
}

initializeBoard(height, width, mines){
   const emptyTiles = this.createEmptyArray(height, width);
   this.populatedTiles = this.populateBoard(emptyTiles, height, width, mines);
   this.neighbourTiles = this.getNumOfMinesNeighbours(populatedTiles,height, width);
}

render() {
   const board = this.renderBoard(this.neighbourTiles, this.state) || null;
   return (
     <div>
        {board}
     </div>
   )
} 

The previous poster answered your first two questions, I'll try to expand a little on the third. 上一张海报回答了您的前两个问题,我将在第三个问题上稍作扩展。

The short answer is #2 is the better practice. 简短的答案是#2是更好的做法。

Try to think of this more as an Object Oriented Programming problem than a react problem. 尝试将其更多地视为面向对象编程问题,而不是反应问题。 The react component you're referencing is just an instance of a react component class. 您引用的react组件只是react组件类的一个实例。 Like any class, they have a constructor function. 像任何类一样,它们具有构造函数。 The idea is that you want to do any state initialization in the constructor. 这个想法是您想在构造函数中进行任何状态初始化。 You want to have your "source of truth" ready to go when you first instantiate the class. 您想在首次实例化该类时准备好“真理之源”。

Therefore, it's a good idea to do your board initialization in the constructor when you first set state. 因此,当您第一次设置状态时,最好在构造函数中进行板初始化。 This way, you avoid any inconsistencies in state between when you first instantiate the class and attempt to manipulate the board. 这样,您可以避免在第一次实例化该类和尝试操纵该板之间的任何状态不一致。 It's also cleaner, easier to understand, and in line with typical OOP principles. 它也更干净,更容易理解,并且符合典型的OOP原则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM