2016-03-18 30 views
0

我有一個包含行的表格,並且可以編輯一行內的每個單元格。有一個按鈕與每行關聯,將該行中的所有單元格提交給數據庫。我想知道的是,如果單元格中的數據已被更改,那麼如何從提交事件實際發生的組件中訪問新值?React - 從嵌套組件訪問更新值

這裏是我說,造表的那一刻:

主表:

import React from 'react'; 
import TableWithDataHeader from './TableWithDataHeader.jsx'; 
import Row from './Row.jsx'; 
import AppStore from '../../stores/AppStore'; 

export default class Table extends React.Component { 

    handleSubmitEvent = (e) => { 
     e.preventDefault(); 
     /////What do I do here to get the updated values???//// 
    }; 

    render() { 
     return (
      <div> 
       <div className="row"> 
        <table className="table table-striped table-bordered"> 
         <thead> 
          <TableWithDataHeader /> 
         </thead> 
         <Row data={AppStore.getCells().historycells} handleSubmitEvent={this.handleSubmitEvent} /> 
        </table> 
       </div> 
      </div> 
     ); 
    } 
} 

行組件:

import React from 'react'; 
import TableBody from './TableBody.jsx'; 
import AppStore from '../../stores/AppStore'; 

export default class Row extends React.Component { 
    state = {data: this.props.data}; 

    handleSubmitEvent = (e) => { 
     this.props.handleSubmitEvent(e); 
    }; 

    render() { 

     let {data} = this.state; 

     return (
      <tbody> 
       <tr id={AppStore.getRowId()}> 
        {this.state.data.map(cell => { 
         return (
          <TableBody key={cell.id} cell={cell.contents} /> 
         ); 
        })} 
        <td className="table-button"> 
         <button type="submit" className="btn btn-primary" onClick={this.handleSubmitEvent.bind(this)}>Save Row</button> 
        </td> 
       </tr> 
      </tbody> 
     ); 
    } 
} 

電池組件:

import React from 'react'; 
import EditableCells from './EditableCells.jsx'; 

export default class TableBody extends React.Component { 

    render() { 
     return (
      <EditableCells data={this.props.cell} /> 
     ); 
    } 
} 

編輯單元格C omponent:

import React from 'react'; 

export default class EditableCells extends React.Component { 
    state = {isEditMode: false, data: ""}; 

    componentWillMount() { 
     this.setState({ 
      isEditMode: this.props.isEditMode, 
      data: this.props.data 
     }); 
    } 

    handleEditCell = (e) => { 
     this.setState({isEditMode: true}); 
    }; 

    handleKeyDown = (e) => { 
     switch (e.keyCode) { 
      case 13: //Enter 
      this.setState({isEditMode: false}); 
      break; 
     } 
    }; 

    handleChange = (e) => { 
     this.setState({data: e.target.value}); 
    }; 

    render() { 

     let {isEditMode, data} = this.state; 

     let cellHtml; 

     if (this.state.isEditMode) { 
      cellHtml = <input type="text" className="form-control" value={this.state.data} onKeyDown={this.handleKeyDown} onChange={this.handleChange} /> 
     } else { 
      cellHtml = <div onClick={this.handleEditCell}>{this.state.data}</div> 
     } 
     return (
      <td className="text-center">{cellHtml}</td> 
     ); 
    } 
} 

如何,我將能夠做到這將是非常有益的,當然的任何幫助,非常感謝!

感謝您的時間

回答

2

儘量保持你的應用程序狀態在組件樹的最高級別最多。在這種情況下,簡單的方法是讓你的表組件處理數據狀態,並提供事件處理程序。將這些作爲道具傳遞給Row,並根據需要進一步向下。概念驗證:https://jsfiddle.net/dannyjolie/4jfxeag8/1/

一般的經驗法則是根本不使用組件狀態,並將應用程序更改的所有更改用於最頂級的組件,但輸入字段有時是規則中的例外,因爲您可能不想在輸入時修改應用程序狀態。

它的基本功能:

export default class Table extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state.cells = ['Foo', 'Bar']; // Fetch something from your store, or better, pass the cells as props from parent component 
    this.handleSubmitEvent = this.handleSubmitEvent.bind(this); 
    this.handleChangeEvent = this.handleChangeEvent.bind(this); 
    } 
    handleSubmitEvent() { 
    // Up to date cells are stored in this.state 
    } 
    handleChangeEvent (value, cell) { 
    // All values are available in this.state, do with that as you wish :) 
    } 
    render() { 
    .... 
    <Row handleSubmitEvent={this.handleSubmitEvent} 
     handleChangeEvent={this.handleChangeEvent} 
     data={this.state.cells} /> 
    .... 
    } 
} 
+0

感謝這個例子幫我整理了一下! – BeeNag

+0

只是想問一個簡單的問題,我將如何去切換輸入,以便在表格首次渲染時不顯示,並通過單擊單元格來訪問它。 – BeeNag

+1

只需使用狀態來跟蹤行是否可編輯,並根據狀態呈現不同的內容。在更新後的示例中,我在渲染輸入和div之間切換,請參閱Row組件:https://jsfiddle.net/dannyjolie/4jfxeag8/5/ – dannyjolie

1

陣營只倒數據的變化,如有必要,重新呈現DOM的自上而下的改變部分。你可以做的是給孩子通過道具組件訪問父組件的狀態:

class ParentComponent extends Component { 
    handleWhatever(updated) { 
    this.setState({ 
     whatever: updated 
    }); 
    } 

    render() { 
    return (
     <ChildComponent onEdit={::this.handleWhatever} /> 
    ); 
    } 
} 

class ChildComponent extends Component { 
    render() { 
    return (
     <SomethingEditable onChange={this.props.onEdit} /> 
    ); 
    } 
} 

所以,這個想法是:

  1. ParentComponent,你定義一個方法,該方法在調用時更改此組件的狀態,即ParentComponent's。
  2. ChildComponent中,每次更改函數時都可以調用函數(最常見的示例:input元素及其onBlur事件)。
  3. 每當您更改ChildComponent中的內容時,它會調用從ParentComponent傳遞過來的函數,而函數會以從下到上的方向提供數據並將其傳遞到ParentComponent。整個子樹的
  4. 的函數被調用,boundParentComponent,所以setState被調用的話,它改變了ParentComponent狀態,它反映了(或沒有)的重新渲染(陣營需要採摘只有那些組件小心,真的必須重新呈現)。

這是一種經典的解決數據移動方向與React預期流動方向相反的問題。

您可以根據需要設置儘可能多的嵌套層,只是不要忘記將該功能傳遞到所有層。