【问题标题】:React/Redux, how to get user inputReact/Redux,如何获取用户输入
【发布时间】:2016-07-09 12:47:24
【问题描述】:

我正在关注usage with React Redux 教程。我真的不明白如何检索用户输入。

他们构建了一个 FilterLink 容器,其 mapDispatchToProps 是

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    onClick: () => {
      dispatch(setVisibilityFilter(ownProps.filter))
    }
  }
}

所以它将自己的Props.filter 注入到连接的展示组件中。如果我们去看看这个容器是如何构造的

const Footer = () => (
  <p>
    Show:{" "}
    <FilterLink filter="SHOW_ALL">All</FilterLink>{", "}
    <FilterLink filter="SHOW_ACTIVE">Active</FilterLink>{", "}
    <FilterLink filter="SHOW_COMPLETED">Completed</FilterLink>
  </p>
)

好的,有“过滤器”属性。这很清楚。

现在我想在同一个示例上构建一个文本过滤器。所以首先这里是我的演示组件

const TodoSearch = ({onSubmit}) => (
    <form
        onSubmit={e => {
            e.preventDefault()
            onSubmit()
        }}
    >
        <input placeholder="Text search" />
        <input type="submit" value="Go" />
    </form>
)

但是当我开始编写容器时,我不知道如何获取用户输入

const mapDispatchToProps = (dispatch) => {
    return {
        onSubmit: () => {
            dispatch(setTextSearch(????))
        }
    }
}

这是我会用 jQuery $(#text).val() 做的事情,但是......这是最好的方法吗?

稍后在同一个教程中,他们构建了一个小表单来将待办事项添加到列表中。好的,我们去看看他们是如何捕捉输入的。

let AddTodo = ({ dispatch }) => {
    let input

    return (
        <div>
            <form onSubmit={e => {
                e.preventDefault()
                if (!input.value.trim()) {
                    return
                }
                dispatch(addTodo(input.value))
                input.value = ''
             }}>
                 <input ref={node => {
                     input = node
                 }} />
                 <button type="submit">
                    Add Todo
                 </button>
            </form>
        </div>
    )
}

等等,这里的魔力在哪里?他们是否使用 ref 技巧将值注入“输入”变量?那是对的吗? 那么如果有 20 个输入字段,我是否应该使用 20 个变量和 20 个不同的 refs?

感谢您的帮助,谢谢

【问题讨论】:

标签: javascript reactjs redux


【解决方案1】:

将您的提交功能更改为以下内容。

const mapDispatchToProps = (dispatch) => {
    return {
        onSubmit: (evt) => {
            dispatch(setTextSearch(evt.target.querySelector('input').value)
        }
    }
}

还有,

const TodoSearch = ({onSubmit}) => (
    <form
        onSubmit={e => {
            e.preventDefault()
            onSubmit(e)
        }}
    >
        <input placeholder="Text search" />
        <input type="submit" value="Go" />
    </form>
)

【讨论】:

  • 我不工作,此时“evt”始终未定义。可能是因为这是一个容器组件而不是一个展示组件?
【解决方案2】:

如果你想获得用户的输入,你可以这样做:

这个演示SearchFormcomponent 渲染了一个输入字段和一个按钮来触发动作。

import React, { Component, PropTypes } from 'react'

export default class SearchForm extends Component {
  constructor(props) {
    super(props)
    this.handleGoClick = this.handleGoClick.bind(this)
  }

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

  handleGoClick() {
    this.props.onChange(this.getInputValue())
  }

  render() {
    return (
      <div>
        <input ref='input' />
        <button onClick={this.handleGoClick}>Go</button>
      </div>
    )
  }
}

请注意,输入字段有一个 ref 值。您可以使用this.refs.input.value 检索当前值。然后handleGoClick 方法将此值传递给动作创建者(通过 mapDispatchToProps 传递到组件的道具中)。

【讨论】:

  • 这不是打破 redux 哲学吗?我不应该在 Container 组件 (mapDispatchToProps) 中而不是在 Presentation 组件中检索输入(无论它是否更新应用程序的状态),因为它是您的 SearchForm?
  • 我个人认为它不会破坏 redux 的理念:(1) 单一事实来源 (2) 状态是只读的 (3) 使用纯函数进行更改。见Three Principles。也许其他人对此有意见?
  • 我相信它违反了第一条规则。正如reactjs.org/docs/uncontrolled-components.html 中提到的,不受控制的组件将真相的来源保存在 DOM 中。
  • FB 不建议这样做。 reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs 我个人也不喜欢 ref(不是 refs),因为它是一个添加的引用,如果您移动嵌套元素,则需要您更改该引用,这使得它的原子性和可移植性降低。
【解决方案3】:

我使用ref获取input的值,handleSubmit()方法在类中,所以可以通过ref获取input。如果你想使用 dispatch 方法,只需在 mapDispatchToProps() 中映射一些 props。

class AddTodo extends Component {

    handleSubmit(event) {
        let input = this.refs.input;
        event.preventDefault();
        if (!input.value.trim()) {
            return
        }
        this.props.addTodo(input.value);
        input.value = ''
    }

    render() {
        return (
            <div>
                <form onSubmit={this.handleSubmit.bind(this)}>
                    <input ref="input"/>
                    <button type="submit">
                        Add Todo
                    </button>
                </form>
            </div>
        );
    }

}

const mapDispatchToProps = (dispatch, ownProps) => {
    return {
        addTodo:(text) => {

            dispatch(addTodo(text));
        }
    }
};

export default connect(null, mapDispatchToProps)(AddTodo);

【讨论】:

  • 如果你能添加一些关于你的代码如何/为什么工作的解释会很棒
【解决方案4】:

这个例子是为了让你更好地理解 react-redux 做典型的 react-redux 事情的方式,比如连接一个组件。这不是学习如何管理输入状态的教程。

因此,为了举例,他们使用ref 属性将input 变量分配给&lt;input/&gt; DOM 节点。然后,可以通过input.value 访问这个输入 DOM 节点的值。

他们使用所谓的Uncontrolled Component,即在内部处理其状态的组件。当您不必处理复杂的表单并且此特定组件的值不打算在其他地方使用时,它会很方便。

但是,假设现在这个待办事项文本需要保存到服务器上。此输入的值现在打算在其他地方使用,在这种情况下,可能在处理 POST 请求的操作创建者中。在这种情况下,表单的值包含在您的 redux 存储中,您现在正在处理 Controlled Component

【讨论】:

    猜你喜欢
    • 2018-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 2019-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多