2016-07-06 65 views
1

我正在製作基於react-redux的文件管理器應用程序,並遇到input的問題。如何更改輸入值以減少

例如,我的代碼:

PathForm.js:

export default class PathForm extends Component { 

    render() { 

    const { currentPath, handleSubmit } = this.props; 
    console.log('PathFormPathFormPathForm', this.props) 

    return (
     <div className="path-box"> 
     <form onSubmit={handleSubmit}> 
      <div> 
      <input type="text" className="current-path-input" placeholder="input path" value={currentPath} /> 
      </div> 
      <button className="go-btn" type="submit">Go</button> 
     </form> 
     </div> 
    ); 
    } 
} 

Explorer.js:

class Explorer extends Component { 

    goPath(e) { 
    e.preventDefault() 
    // fake function here, because I have to solve the input problem first 
    console.log('PathForm goPath:',this.props) 
    let {targetPath , actions} = this.props 
    swal(targetPath) 
    } 

    render() { 
    const { node, currentPath , actions} = this.props 
    console.log('Explorer.render:',this.props) 

    return (
     <div className='explorer-container'> 
     <PathForm currentPath={currentPath} handleSubmit={this.goPath.bind(this)}/> 
     <FileListOperator /> 
     <FileListView fileList={node && node.childNodes} actions ={actions} /> 
     </div> 
    ); 
    } 
} 


function mapStateToProps(state, ownProps) { 
    return { 
    node: state.tree[state.tree.currentPath], 
    currentPath: state.tree.currentPath 
    }; 
} 

function mapDispatchToProps(dispatch) { 
    console.log('mapDispatchToProps') 
    return { 
    actions: bindActionCreators(NodeActions, dispatch) 
    }; 
} 

export default connect(
    mapStateToProps, 
    mapDispatchToProps 
)(Explorer); 

特點我想:

我有一個PathForm ,它需要從兩種方式顯示路徑:

  1. 用戶單擊左樹視圖中的文件路徑,Explorer得到這個路徑currentPath,然後傳遞給PathForm,並在輸入顯示currentPath
  2. 用戶直接鍵入路徑PathForm的輸入,PathForm調用handleSubmit(資源管理器的功能)來改變currentPath

    附加:我想保持PathForm爲無狀態組件

問題

  1. 我想使用PathForm爲無狀態的形式,所以我不希望將其連接到存儲,但我需要它由currentPath改變輸入。但是,如果我設置value={currentPath},則用戶無法輸入其他任何內容。
  2. 變化<input type="text" onChange={this.changeValue} value={this.getValue()}/>允許用戶類型的字符串在此輸入,但不能利用Explorer
  3. 過去,我能想象是連接這種形式來存儲我不想只有這樣,道具currentPath。我希望Explorer派遣所有行動並傳遞道具。

試圖與一些包

我發現輸入不作爲我的想法,所以我嘗試了兩種流行的包:

  1. redux-form

    它創建一個表單需要這麼多的代碼,官方的文檔不會說如何渲染這個表單親子道具, 我試圖通過propshandleSubmit到它,不工作。我看到 React + Redux - What's the best way to handle CRUD in a form component?How to wire up redux-form bindings to the form's inputs 我發現我不能這樣做,它定義了一些函數覆蓋我的,這種行爲對我不好(我必須改變handlerSubmit函數名稱,但它仍然不起作用),並且它連接到商店。所以我轉formsy-react

  2. formsy-react

    它仍然需要這麼多的代碼,但它提供了一些mixin,但我仍然需要編寫與changeValue功能自己的自定義文本輸入(changeValue在大多數情況下沒有必要寫正常html jquery app時)。然後我發現這個問題是PathForm不能使用由Explorer通過道具currentPath ...

可能工作的解決方案(但我不傾向於使用):

連接PathForm存儲,爲此輸入添加另一個狀態inputPathValue。使用inputPathValuecurrentPath


以上互動之後,我發現使用的輸入/形式是,在方便的反應超級.... 這是否意味着我必須PathForm連接到Stroe的? 任何其他方式來解決我的問題?

回答

7

在reactjs中有uncontrolled(未設定值)和controlled(設定值)輸入。

controlled不允許用戶輸入,但uncontrolled呢。

解決方案:

  1. 需要使用uncontrolled input(沒有值屬性)。
  2. 選擇輸入元素並設置currentPath更改時的值。

糟糕的方式:

代碼:

export default class PathForm extends Component { 
    changeCurrentPath(path) { 
    const pathInput = document.querySelector('.current-path-input') 
    if (pathInput){ 
     pathInput.value = path 
     this.lastPath = path 
    } 
    } 

    render() { 

    const { currentPath, handleSubmit } = this.props; 
    console.log('PathFormPathFormPathForm', this.props) 

    this.changeCurrentPath(currentPath) 

    return (
     <div className="path-box"> 
     <form onSubmit={handleSubmit}> 
      <div> 
      <input type="text" className="current-path-input" placeholder="input path" /> 
      </div> 
      <button className="go-btn" type="submit">Go</button> 
     </form> 
     </div> 
    ); 
    } 
} 

好方法:

使用componentWillReceiveProps送等道具和rel選擇元素

1.使用表單提交

export default class PathForm extends Component { 

    constructor(props) { 
    super(props) 
    // can not find `this` if not bind 
    this.handleSubmit = this.handleSubmit.bind(this) 
    } 

    componentWillReceiveProps(nextProps) { 
    if (nextProps.currentPath !== this.props.currentPath) { 
     this.setInputValue(nextProps.currentPath) 
    } 
    } 

    getInputValue() { 
    return this.refs.pathInput.value 
    } 

    setInputValue(val) { 
    this.refs.pathInput.value = val 
    } 

    handleSubmit(e){ 
    e.preventDefault() 
    this.props.handleSubmit(this.getInputValue()) 
    } 

    render() { 

    return (
     <div className="path-box"> 
     <form onSubmit={this.handleSubmit}> 
      <input className="current-path-input" 
      defaultValue={this.props.currentPath} 
      ref="pathInput" /> 
      <button className="waves-effect waves-light btn" type="submit">Go</button> 
     </form> 
     </div> 
    ); 
    } 
} 

2.使用按鈕單擊

export default class PathForm extends Component { 

    constructor(props) { 
    super(props) 
    // can not find `this` if not bind 
    this.handleGoClick = this.handleGoClick.bind(this) 
    this.handleKeyUp = this.handleKeyUp.bind(this) 
    } 

    componentWillReceiveProps(nextProps) { 
    if (nextProps.currentPath !== this.props.currentPath) { 
     this.setInputValue(nextProps.currentPath) 
    } 
    } 

    getInputValue() { 
    return this.refs.pathInput.value 
    } 

    setInputValue(val) { 
    this.refs.pathInput.value = val 
    } 

    handleKeyUp(e) { 
    if (e.keyCode === 13) { 
     this.handleGoClick() 
    } 
    } 

    handleGoClick(e) { 
    e.preventDefault() 
    this.props.handleSubmit(this.getInputValue()) 
    } 

    render() { 

    return (
     <div className="path-box"> 
     <form > 
      <input className="current-path-input" 
      defaultValue={this.props.currentPath} 
      onKeyUp={this.handleKeyUp} 
      ref="pathInput" /> 
      <button className="waves-effect waves-light btn" type="submit" onClick={this.handleGoClick}>Go</button> 
     </form> 
     </div> 
    ); 
    } 
} 
0

如果你真的不想在終極版的狀態下,可以代替用setState存儲組件上的狀態。直接訪問輸入強烈不鼓勵。您應該跟蹤組件上的輸入狀態。在輸入處添加onChange處理程序,存儲狀態並處理componentWillReceiveProps,您可以在其中決定如何處理新的傳入道具。