【问题标题】: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))

【问题讨论】:

    标签: javascript reactjs material-ui


    【解决方案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 如何在具有多个输入的表单中使用状态,它非常慢!
    猜你喜欢
    • 2021-02-23
    • 2020-05-04
    • 2018-07-23
    • 2021-06-06
    • 2021-11-02
    • 1970-01-01
    • 1970-01-01
    • 2018-08-18
    • 1970-01-01
    相关资源
    最近更新 更多