在 Material-UI 中使用 React 的 'ref' 属性

Posted

技术标签:

【中文标题】在 Material-UI 中使用 React 的 \'ref\' 属性【英文标题】:Using React's 'ref' attribute with Material-UI在 Material-UI 中使用 React 的 'ref' 属性 【发布时间】:2018-09-28 11:38:37 【问题描述】:

我正在尝试在 Material-UI 中的 TextField 上使用 React 的“ref”属性访问输入数据。似乎没有一种简单的方法可以通过“inputRef”或“inputProps”来做到这一点。

下面的示例在第 26 行显示了 inputProps 的使用。将 TextField 的名称分配给 'ref' 属性似乎不会产生有效的对象。

使用“inputRef”,根据Material-ui 文档强制使用函数,尝试将字段数据作为属性传递也不起作用。例如:(txt => this.name = txt)

有人找到解决办法了吗?

class MediaForm extends Component 
  constructor (props) 
    super(props)
    this.state = 
    this.handleSubmit = this.handleSubmit.bind(this)
  

  handleSubmit (e) 
    const  title, colour  = this.refs
    e.preventDefault()
    window.alert(`New colour: $title.value $colour.value`)
  

  render () 
    const  classes  = this.props
    return (
      <form className=classes.root
        onSubmit=this.handleSubmit>
        <div className=classes.field>
          <TextField
            name='title'
            type='text'
            label='Title'
            placeholder='Movie title...'
            autoFocus
            inputProps=ref: this.name
            required />
        </div>
        <div className=classes.field>
          <Tooltip title='Add a colour the reflects the mood of the film'>
            <TextField
              name='colour'
              type='color'
              label='Mood'
              inputProps=ref: this.name
              required />
          </Tooltip>
        </div>
        <Button
          variant='raised'
          color='primary'
          className=classes.button>
          ADD
        </Button>
      </form>
    )
  


MediaForm.propTypes = 
  classes: PropTypes.object.isRequired


export default withRoot(withStyles(styles)(MediaForm))

【问题讨论】:

【参考方案1】:
class MediaForm extends Component 
  refs =   // <____ notice this
  constructor (props) 
    super(props)
    this.state = 
    this.handleSubmit = this.handleSubmit.bind(this)
  

  handleSubmit (e) 
    const  title, colour  = this.refs
    e.preventDefault()
    window.alert(`New colour: $title.value $colour.value`)
  

  render () 
    const  classes  = this.props
    return (
      <form className=classes.root
        onSubmit=this.handleSubmit>
        <div className=classes.field>
          <TextField
            inputProps=ref => this.refs.title = ref
            name='title'
            type='text'
            label='Title'
            placeholder='Movie title...'
            autoFocus
            required />
        </div>
        <div className=classes.field>
          <Tooltip title='Add a colour the reflects the mood of the film'>
            <TextField
              name='colour'
              inputProps=ref => this.refs.colour = ref
              type='color'
              label='Mood'
              required />
          </Tooltip>
        </div>
        <Button
          variant='raised'
          color='primary'
          className=classes.button>
          ADD
        </Button>
      </form>
    )
  


MediaForm.propTypes = 
  classes: PropTypes.object.isRequired


export default withRoot(withStyles(styles)(MediaForm))

【讨论】:

查看您编辑的第 22 行:ref= =ref => this.refs.title = ref,如果您的意思是 ref=ref => this.refs.title = ref,不要认为 'refs' 可以作为无状态组件传递给 TextField。不用担心。反正我只是好奇。感谢您的及时回复。【参考方案2】:

你不需要参考。提交事件包含作为目标的表单。您可以通过form.elements 访问表单中的输入:

handleSubmit (event) 
    const  title, colour  = event.currentTarget.elements;
    event.preventDefault();
    window.alert(`New colour: $title.value $colour.value`);

关于你的裁判的问题:this.name 指的是什么?您没有在任何地方声明它,所以它是undefined。将 undefined 传递给 ref 属性无效。还有如何将两个输入引用绑定到同一个实例属性name。您是否知道您的渲染函数中的this 指的是您的MediaForm 组件的实例,因此this.name 是您的组件实例上的属性name(未定义)?

如果您想为每个输入获取单独的参考,您应该使用callback pattern。注意String refs are deprecated 不应该被使用:

render() 
    return(
        <TextField
            name='title'
            type='text'
            label='Title'
            placeholder='Movie title...'
            autoFocus
            inputProps=ref: input => this.titleInput = input
            required 
        />
    );

编辑:

您可能想要的是controlled component。在这种模式中,您的父组件会跟踪其子组​​件(通常是输入)的值:

class MediaForm extends Component 
    constructor(props) 
        super(props);
        this.state = 
            title: '',
            colour: '',
        ;
    

    handleChange = event => 
        const name, value = event.currentTarget;
        this.setState([name]: value);
    ;

    handleSubmit = event => 
        event.preventDefault();
        const title, colour = this.state;
        window.alert(`New colour: $title $colour`);
    ;

    render() 
        const classes = this.props;
        const title, colour = this.state;

        return (
            <form className=classes.root onSubmit=this.handleSubmit>
                <div className=classes.field>
                    <TextField
                        name="title"
                        type="text"
                        value=title
                        onChange=this.handleChange
                        label="Title"
                        placeholder="Movie title..."
                        required
                    />
                </div>
                <div className=classes.field>
                    <Tooltip title="Add a colour the reflects the mood of the film">
                        <TextField
                            name="colour"
                            type="color"
                            value=colour
                            onChange=this.handleChange
                            label="Mood"
                            required
                        />
                    </Tooltip>
                </div>
                <Button
                    type="submit"
                    variant="raised"
                    color="primary"
                    className=classes.button
                >
                    ADD
                </Button>
            </form>
        );
    

现在您的父母可以通过this.state.titlethis.state.colour 完全控制和访问每个输入的值。这里也不需要任何参考。

【讨论】:

你是对的。我的错。 TextFieldinputProps 需要一个值,而且绝对不需要(this.name)。我也很欣赏从输入字段传递ref 不是推荐的方式。但是,问题仍然存在:是否可以在 Material-UI TextField 上接收一个值作为输入,将其分配给 ref,然后将其传递给要访问的提交处理程序通过this.refs.titlethis.ref.colour? @JohnLamy 只是为了正确理解:您基本上希望将输入的值作为父组件中的变量访问,以便您可以在提交处理程序中使用它们? @JohnLamy 欢迎您。如果您觉得这可以解决您的问题,请点赞/标记为已接受的答案。 感谢您提醒我,我不需要使用 refs 或绑定任何事件来使其工作。从字面上看,每篇关于表单和事件的 React 文章都依赖于引用和绑定。 @JohnLamy 如何在具有多个输入的表单中使用状态,它非常慢!

以上是关于在 Material-UI 中使用 React 的 'ref' 属性的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React 测试库中获取 Material-UI 密码输入

如何在 React-Amin 创建组件中使用 Steppers 添加 Material-UI 表单

如何在 React 中使用 Material-UI 在 onFocus 事件的 Textfield 中选择部分文本?

在 React 中使用 material-ui makeStyles 的钩子调用无效

如何使 Material-UI Dialog 在 React 中工作

React + Jest单元测试中的Material-UI排版错误