2016-09-21 111 views
0

修復陣營接收道具

當添加這種方法首次該元素被呈現輸入不更新,它具有訪問props接收的時候了。

componentDidMount() { 
    if (typeof this.props.options.value !== "undefined") 
    this.setState({value: this.props.options.value}) 
}, 

我有幾個反應元素幾乎按預期工作。我有一個視圖,其中包含一系列元素和一個模式視圖來編輯它們。當單擊某個元素的編輯按鈕時,該元素將被設置爲選中的狀態,並顯示模態窗體(將其作爲道具傳遞給該元素)。

showUpdateForm(poiIndex) { 
    this.setState({selectedPoi: this.state.pois[poiIndex]}) 
    $('#updatePoiModal').modal('show') 
    console.log('shown') 
}, 

...render()... 
<UpdatePoiForm poi={this.state.selectedPoi} ref="updatePoiForm" successHandler={this.successUpdateHandler}/> 

當項目被點擊模態視圖正確顯示,但是,通過不顯示文本值;顯示前一個選定元素的元素(如果是第一個元素,則爲空框)。這裏是模態的視圖的呈現方法:

render() { 
    console.log('rendering') 
    if(!this.props.poi) 
    return null 
    console.log(this.props.poi.name) 
    var poi = this.props.poi 

    var config = { 
    url: `${context.apiUrl}user/pois/${poi.id}`, 
    method: 'PUT', 
    successMessage: 'El Punto de Interés fue actualizado', 
    successHandler: this.successHandler, 
    hideSubmitButton: true, 
    fields: { 
     name: { 
     label: 'Nombre', 
     type: 'text', 
     value: this.props.poi.name 
     }, 
     location: { 
     label: 'Ubicación', 
     type: 'text', 
     display: false, 
     value: this.props.poi.location 
     }, 
     category_id: { 
     label: 'Categoría', 
     type: 'select', 
     options: context.poi_categories.map((cat) => { 
      return {value: cat.id, desc: cat.name} 
     }) 
     } 
    } 
    } 

    return (
    <div> 
     <Row> 
     <Col size="12"> 
      <Panel> 
      <PanelBody> 
       <FormComponent config={config} ref="form"/> 
      </PanelBody> 
      </Panel> 
     </Col> 
     <Col size="12"> 
      <Panel> 
      <PanelHeading heading="Selecciona la ubicación" /> 
      <Map height="400px" ref="map_update_poi" zoom="15"/> 
      </Panel> 
     </Col> 

     </Row> 
    </div> 
) 
} 

這裏是形式分量的渲染方法:

render() { 
    elems = [] 
    count = 0 

    for (var key in this.props.config.fields) { 
    console.log(this.props.config.fields[key]) 
    var _type = this.props.config.fields[key].type 
    var config = { 
     key: count++, 
     options: this.props.config.fields[key], 
     ref: key, 
     refName: key, 
     fullWidth: this.props.config.fullWidth, 
    } 

    switch (_type) { 
     case 'text': 
     elems.push(<InputElement {...config}/>) 
     break 
     case 'select': 
     elems.push(<SelectElement {...config}/>) 
     break 
     case 'multipleSelect': 
     elems.push(<MultipleSelectElement {...config}/>) 
     break 
     case 'button': 
     elems.push(<ButtonElement {...config}/>) 
     break 
     case 'switcher': 
     elems.push(<SwitcherElement {...config}/>) 
     break 
     case 'timePicker': 
     elems.push(<TimePickerElement {...config}/>) 
     break 
     case 'radio': 
     elems.push(<RadioElement {...config}/>) 
     break 
     case 'autocomplete': 
     elems.push(<AutoCompleteInputElement {...config}/>) 
     break 
    } 
    } 
    console.log(elems) 

    return (
    <form action="#" className="form-horizontal"> 
     <div className="form-content"> 
     {elems} 
     {!this.props.config.hideSubmitButton ? <div className="form-buttons"> 
      <div className="row"> 
      <div className="col-md-offset-3 col-md-9"> 
       <button type="submit" onClick={this.handleSave} 
         className="btn btn-blue btn-ripple">Crear</button> 
      </div> 
      </div> 
     </div> : null} 
     </div> 
    </form> 
) 
} 

而渲染所述輸入元件(除去變量聲明爲簡潔起見,沒有方法缺少):

render() { 
    return (
    <div className={formClass} style={style}> 
     <label className="control-label col-md-3">{this.props.options.label}</label> 
     <div className={inputClass}> 
     <div className="inputer"> 
      <div className="input-wrapper"> 
      <input ref={this.props.refName} type="text" className="form-control" onFocus={this.props.onFocus} 
       placeholder={this.props.placeholder} value={this.state.value} onChange={this.handleChange}/> 
      </div> 
      {validationMsg} 
     </div> 
     </div> 
    </div> 
) 
} 

最後,我檢查輸入的道具在這裏:

componentWillReceiveProps(nextProps) { 
    console.log('input element', nextProps) 
    if (typeof this.props.options.value !== "undefined") 
    this.setState({value: this.props.options.value}) 
}, 

我已經在鏈的每個「停止」中添加了日誌語句。模態視圖正確顯示元素,表單顯示最後一個單元的字符串,輸入元素的道具也顯示最近單擊元素的信息。但是,在呈現輸入時,this.state.value爲null(這是getInitialState()中給出的值)或上一個元素的值。根據日誌的順序,道具在渲染前被接收。雖然我知道狀態更新不是直接的,但如果渲染髮生了,那麼狀態的改變應該再次觸發渲染,這次使用正確的值,但是這並沒有發生,我不明白爲什麼!

shown 
list index 1 
name Object { label="Nombre", type="text"} 
location Object { label="Ubicación", type="text", display=false} 
category_id Object { label="Categoría", type="select", options=[2]} 
[Object { key="0", ref="name", props={...}, more...}, Object { key="1", ref="location", props={...}, more...}, Object { key="2", ref="category_id", props={...}, more...}] 
input props Object { options={...}, refName="name", fullWidth=undefined} 
render input null 
input props Object { options={...}, refName="location", fullWidth=undefined}componentWillReceiveProps index.js (line 35220) 
render input null 
** At this point the new element is received ** 
** The objects didn't paste completely, but the correct values are 
    there this time. However, there is no output from componentWillReceiveProps ** 
new poi test02 
rendering update form 
update form test02 
name Object { label="Nombre", type="text", value="test02"} 
location Object { label="Ubicación", type="text", display=false, more...} 
category_id Object { label="Categoría", type="select", options=[2]} 
[Object { key="0", ref="name", props={...}, more...}, Object { key="1", ref="location", props={...}, more...}, Object { key="2", ref="category_id", props={...}, more...}] 
2 render input null 
Object { category="Almacen", category_id=1, id=627, more...} 

編輯2: 現在這個問題只發生在第一次點擊。發生時,我將this.props替換爲@P @ e @ Radio-的建議中的nextProps。

回答

1

componentWillReceiveProps,設置狀態來nextProps.options.value而不是this.props.options.value

componentWillReceiveProps(nextProps) { 
    if (typeof nextProps.options.value !== "undefined") 
    this.setState({value: nextProps.options.value}) 
}, 

如果它是第一個渲染,componentWillReceiveProps不叫,所以你可以使用componentDidMount與此。props實現相同:

componentDidMount() { 
    if (typeof this.props.options.value !== "undefined") 
    this.setState({value: this.props.options.value}) 
} 
+0

謝謝,我沒有看到那個錯誤。但是,問題依然存在。使用所選元素設置道具後,渲染不會被觸發。我將編輯問題以包含控制檯輸出。 – gamda

+0

我之前沒有注意到,但是更改解決了第一次之後每次點擊的問題。第一個仍然有問題 – gamda

+0

componentWillReceiveProps不會在第一個渲染上被調用。你需要使用componentWillMount或者有一個默認工作的初始狀態 –