如何在redux中更改输入值

Mit*_*ril 2 forms input ecmascript-6 reactjs redux

我正在制作一个基于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>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

我想要的功能:

我有一个PathForm,它需要从两个方面显示路径:

  1. 用户从左侧树视图中单击文件路径,Explorer获取此路径currentPath,然后传递给输入PathForm并显示currentPath
  2. 用户直接键入输入的路径PathForm, PathForm调用handleSubmit(Explorer的函数)来改变currentPath

    附加:我想保留PathForm作为无状态组件

问题:

  1. 我想PathForm用作无状态表单,所以我不想将它连接到存储,但我需要它改变输入currentPath.但如果我设置value={currentPath},用户不能输入任何其他内容.
  2. 更改为<input type="text" onChange={this.changeValue} value={this.getValue()}/>允许用户在此输入中键入字符串,但不能使用currentPath传递的道具Explorer
  3. 我能想象的唯一方法是将这个表单连接到我不想要的商店.我想Explorer发送所有动作并传递道具.

尝试了一些包

我发现输入不是我的想法,所以我尝试了两个流行的包:

  1. redux-form

    它创建一个表单需要这么多的代码,和官方的文档没有说如何使这种形式与父母的道具,我试图通过propshandleSubmit给它,不行.在看到 React + Redux之后 - 在表单组件中处理CRUD的最佳方法是什么?如何连接起来Redux的形式绑定到窗体的投入 ,我发现我不能做到这一点,它定义了一些功能覆盖矿山,这表现得并不好,我(我不得不改变handlerSubmit函数的名称,但它仍然不工作),它连接到商店.所以我转向formsy-react

  2. formsy-react

    它仍然需要这么多代码,虽然它提供了一些mixin,但我仍然需要自己编写一个带有changeValue函数的自定义文本输入(changeValue在大多数情况下写正常时不需要html jquery app).然后我发现了PathForm不能使用道具currentPath传递的问题Explorer. ..

可能工作的解决方案(但我不倾向于使用):

连接PathForm到商店,inputPathValue为此输入添加另一个状态.使用inputPathValue互动currentPath


在上面之后,我发现使用输入/表单是超级方便的反应....这是否意味着我必须连接PathForm到stroe?还有其他方法可以解决我的问题吗?

Mit*_*ril 9

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>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

好办法:

用于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>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

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>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)