如何从孩子到父母的状态做出反应

时间:2017-07-09 12:50:41

标签: javascript reactjs

我是React的新人

我有两个组成部分。家长Square,孩子Row

我希望将cellTop中的setValues cellLeftRow设置为父级并使用它。

我该怎么做。

我的代码如下:



var Square = React.createClass({


	getInitialState: function () {

		return {

		countRow: 4,
		countCol: 4,
		mouseOnTable: false,
		onDelRow: false,
		onDelCol: false

		}

	},


	appendCol: function() {

		var countColNew = this.state.countCol + 1;

		this.setState({countCol: countColNew});  //change initiale state "countCol" (add new column)

		//console.log(this.state.countCol)

	},

	appendRow: function() {

		var countRowNew = this.state.countRow + 1;

		this.setState({countRow: countRowNew});  //change initiale state "countRow" (add new row)

		//console.log(this.state.countRow)

	},

	deleteCol: function() {

		var countColNew = this.state.countCol - 1;

		this.setState({countCol: countColNew});  //change initiale state "countCol" (delete col)

		//console.log(this.state.countCol)

	},

	deleteRow: function() {

		var countRowNew = this.state.countRow - 1;

		this.setState({countRow: countRowNew});  //change initiale state (delete row)

		//console.log(this.state.countRow)

	},


	hiddenButtons: function(){
		var mouseOnTableNew = true;
		this.setState({mouseOnTable: mouseOnTableNew})
	},


	showButtons: function(){
		var mouseOnTableNew = false;
		this.setState({mouseOnTable: mouseOnTableNew})
	},



	render: function() {

		var timeOut;


		return (

			<div className='square'>

				<table className='square__table'
						 onMouseOver={this.hiddenButtons}						 									
						 onMouseLeave={() => {timeOut=setTimeout(this.showButtons,200)}}>


							<Row countRow={this.state.countRow}
								 countCol={this.state.countCol}
								 ref={(ref) => this.state}

								 />		


				</table>


							<button className="square__button square__button_append square__button_col-append"
									onClick={this.appendCol}>
							</button>


					        <button className="square__button square__button_delete square__button_col-delete" 
					        		style={this.state.countCol===1 ||
					        			   this.state.mouseOnTable===false ||
					        			   this.state.onDelRow===true ? {visibility: "hidden"} : {visibility: "visible"}}

					        		onClick={this.deleteCol}
					        		onMouseOver={() => {clearTimeout(timeOut);
					        							this.setState({onDelCol:true})}}
					        		onMouseLeave={() => {this.setState({onDelCol:false})}}>
					        </button>


					        <button className="square__button square__button_append square__button_row-append" 
					        		onClick={this.appendRow}>
					        </button>


					        <button className="square__button square__button_delete square__button_row-delete"
					        		style={this.state.countRow===1 ||
					        			   this.state.mouseOnTable===false ||
					        			   this.state.onDelCol===true ? {visibility: "hidden"} : {visibility: "visible"}} 

					        		onClick={this.deleteRow}

					        		onMouseOver={() => {clearTimeout(timeOut);
					        							this.setState({onDelRow:true})}}

					        		onMouseLeave={() => {this.setState({onDelRow:false})}}>
					        </button>



				

			</div>


		)

	}

})


//==================================================


var Row = React.createClass({



	getInitialState: function(){
		return {

			cellTop: 0,
			cellLeft: 0,

		}


	},



	createCol: function() {

		var columns = [];

		for(let i = 0; i < this.props.countCol; i++){
			columns.push(this.createCell)
		}

		return columns;


	},



	createRow: function (k) {

		return (

			<tr key={k}>
				{this.createCol().map(function(cell,key){
					return (
							cell(key)
						)
				})}
			</tr>
		)
	},



	createCell: function(k){

		return (

			<td key={k}>
				<div className="square__cell" onMouseOver={this.getMousePosition}></div>
			</td>
		)

	},


	getMousePosition: function(element){

		let coordinates = element.target.getBoundingClientRect();
		let top = coordinates.top;
		let left = coordinates.left;
		
		this.setState({
			cellTop: top,
			cellLeft: left
		})


	},



	render: function(){

			var lines = []
			for (let i = 0; i < this.props.countRow; i++) {
			lines.push(this.createRow(i))
		}


		return (

			<tbody>		
				{lines}
			</tbody>
		)
	}



})
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

我建议你根本不要在组件中使用state。当您想要控制子组件的父组件时,这只会导致问题。

相反,

  • 使所有组件通过道具接收数据
  • 将状态和所有数据移动到外部对象(商店)
  • 在数据更改时让商店更新您的组件
  • 来自组件只是更新商店

查看https://github.com/reflux/refluxjs

+---------+       +--------+       +-----------------+
¦ Actions ¦------>¦ Stores ¦------>¦ View Components ¦
+---------+       +--------+       +-----------------+
     ^                                      ¦
     +--------------------------------------+

答案 1 :(得分:1)

您可以向子组件传递一个回调函数,该函数接受两个参数cellTopcellLeft。在您的子组件中,在您的子组件中调用cellTop函数的同时传递cellLeftgetMousePosition()值。

在您的父组件中创建一个如下函数:

handleSizeChange: function(cellTop, cellLeft){
    this.setState({
        cellTop: cellTop,
        cellLeft: cellLeft
    })
},

在您的父<Row>组件中,将回调函数作为这样的道具传递:

<Row countRow={this.state.countRow}
     countCol={this.state.countCol}
     ref={(ref) => this.state}
     onSizeChange={this.handleSizeChange}
/>

在您的子组件中,将this.props.handleSizeChange(top, left)添加到getMousePostion()功能:

getMousePosition: function(element){

    let coordinates = element.target.getBoundingClientRect();
    let top = coordinates.top;
    let left = coordinates.left;

    this.setState({
        cellTop: top,
        cellLeft: left
    })

    this.props.handleSizeChange(top, left)
},

同样正确的是,只要有可能,最好的数据来自Parent - &gt; Child组件,但回调函数对于按钮事件等常见功能很常见。您可以使用类似Redux的东西来处理状态管理,但这是相当高级的,如果这是一个简单的初学者应用程序,则可能有点过分。

此外,您应该使用组件的最新React语法。创建这样的新类:

import React, { Component } from 'react'

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

          //getinitialstate
          this.state = {
            cellTop: 0,
            cellLeft: 0
          }
      }
}

并定义类方法:

  componentWillMount() {
    // this runs right before the <App> is rendered

  })
相关问题