如何正确设置对React组件的引用?

时间:2016-03-09 12:30:02

标签: reactjs redux

将React与react-redux一起使用,我试图获取此登录表单:

import React from 'react'
import RaisedButton from 'material-ui/lib/raised-button';
import TextField from 'material-ui/lib/text-field';
const LoginButton = () => (
  <form>
    <div>
      <TextField hint="E-mail" floatingLabelText="E-mail" ref="emailInput"></TextField><br/>
    </div>
    <div>
      <TextField hint="Contraseña" floatingLabelText="Contraseña" type="password" ref="passwordInput"></TextField><br/><br/>
    </div>
    <div>
      <RaisedButton label="Acceder" primary={true} onClick={e => {
          console.log(emailInput.value);
        }}/>
    </div>
  </form>
);

export default LoginButton;

同时它被用作:

import React from 'react'
import Card from 'material-ui/lib/card/card';
import CardActions from 'material-ui/lib/card/card-actions';
import CardHeader from 'material-ui/lib/card/card-header';
import CardText from 'material-ui/lib/card/card-text';
import CardTitle from 'material-ui/lib/card/card-title';
import RaisedButton from 'material-ui/lib/raised-button';

import Paper from 'material-ui/lib/paper';
import { Link } from 'react-router'
import LoginForm from '../containers/LoginForm'

const divStyle = {
  marginTop: '100px'
};

const paperStyle = {
  padding: '25px'
}

const Login = () => (
  <div className="row center-md" style={divStyle}>
    <div className="col-md-6">
      <div className="box">
        <Paper zDepth={4} style={paperStyle}>
          <div>
            <h1>Acceder</h1>
          </div>
          <LoginForm />
        </Paper>
      </div>
    </div>
  </div>
);

export default Login;

因此,我正在运行这个:

Uncaught Invariant Violation: Stateless function components cannot have refs.

所以我有一些问题,我该如何解决这个错误?什么是神奇的允许我导出这样的组件而不是导出React.createClass(我已经从几个react / redux示例中复制了这个模式)?

3 个答案:

答案 0 :(得分:5)

在无状态组件中,您可以使用这种方法:

const TextFieldSubmit = (props) => {
  let input;

  return (
    <div className='ui input'>
      <input
        ref={node => input = node}
        type='text'
      >
      </input>
      <button
        onClick={() => {
          props.onSubmit(input.value);
          input.value = '';
        }}
        className='ui primary button'
        type='submit'
      >
        Submit
      </button>
    </div>
  );
};

有关详细信息,请访问:https://www.fullstackreact.com/p/using-presentational-and-container-components-with-redux/

答案 1 :(得分:3)

TL;博士

您使用的是Stateless Componentref属性无法与此类组件一起使用。

长答案

Stateless components可以被视为&#34;静态html&#34;,它们只有props作为函数的第一个参数。

他们无法拥有staterefs生命周期方法

您需要创建React.Component才能使用ref属性。您可以通过两种方式创建此组件:

如果您不使用ES6,或者您需要使用mixins属性,则应执行以下操作:
var React = require("react");

module.exports = React.createClass({
  render() {
    return (
      <form>
        <div>
          <TextField hint="E-mail" floatingLabelText="E-mail" ref="emailInput"></TextField><br/>
        </div>
        <div>
          <TextField hint="Contraseña" floatingLabelText="Contraseña" type="password" ref="passwordInput"></TextField><br/><br/>
        </div>
        <div>
          <RaisedButton label="Acceder" primary={true} onClick={e => {
              console.log(emailInput.value);
            }}/>
        </div>
      </form>
    );
  }
});
如果您使用的是ES6
import React, { Component } from "react"

export default class Form extends Component {
  render() {
    return (
      <form>
        <div>
          <TextField hint="E-mail" floatingLabelText="E-mail" ref="emailInput"></TextField><br/>
        </div>
        <div>
          <TextField hint="Contraseña" floatingLabelText="Contraseña" type="password" ref="passwordInput"></TextField><br/><br/>
        </div>
        <div>
          <RaisedButton label="Acceder" primary={true} onClick={e => {
              console.log(emailInput.value);
            }}/>
        </div>
      </form>
    );
  }
}

答案 2 :(得分:2)

使用React提供的无状态函数组件语法定义这些组件。来自React docs:

  

这个简化的组件API适用于作为其道具的纯函数的组件。这些组件不得保留内部状态,不具有后备实例,并且不具有组件生命周期方法。它们是输入的纯函数变换,没有样板。但是,您仍然可以通过将它们设置为函数的属性来指定.propTypes和.defaultProps,就像在ES6类上设置它们一样。

此处描述了您遇到的问题:

  

注意:   由于无状态函数没有后备实例,因此您无法将ref附加到无状态函数组件。通常这不是问题,因为无状态函数不提供命令性API。如果没有命令式API,那么无论如何都无法对一个实例做很多事情。但是,如果用户想要找到无状态函数组件的DOM节点,则它们必须将组件包装在有状态组件(例如,ES6类组件)中,并将ref附加到有状态包装器组件。

如果您需要此参考,请更改LoginButton组件以使用标准class LoginButton extends React.Component组件声明语法,或将无状态功能组件包装在有状态组件中。

了解更多here