在材质UI RaisedButton Label中允许变量

时间:2016-09-16 12:54:06

标签: javascript reactjs material-ui

我正在玩React和Material,我正在徘徊如何在Material UI组件标签中传递变量?

这是我的代码:

const LoginForm = ({
    myVariable
}) => (
    {/*....*/}
    <RaisedButton type="submit" label={myVariable} primary/>
    {/*....*/}
);

LoginForm.propTypes = {
    myVariable : PropTypes.string.isRequired
};

export default LoginForm;

但是,即使标签在浏览器中正确显示(铬),控制台也会显示此警告:

warning.js:36 Warning: Failed prop type: Required prop label or children or icon was not specified in RaisedButton.

修改 经过一些调试后,会发生视图渲染多次(至少4次???),而在第一次渲染中,myVariable未定义。

所以,现在,我必须管理为什么组件被渲染为多个时间以及为什么在第一次渲染中,变量是未定义的。

所以这是我的代码。

Base.jsx

import React, {PropTypes} from 'react';
import {Link, IndexLink} from 'react-router';

const Base = ({
  children
}) => (
  <div>
    <div className="top-bar">
    {children}
  </div>
);

Base.propTypes = {
  children: PropTypes.object.isRequired
};

export default Base;

Auth.js

class Auth {

  /**
   * Authenticate a user. Save a token string in Local Storage
   *
   * @param {string} token
   */
  static authenticateUser(token) {
    localStorage.setItem('token', token);
  }

  /**
   * Check if a user is authenticated - check if a token is saved in Local Storage
   *
   * @returns {boolean}
   */
  static isUserAuthenticated() {
    return localStorage.getItem('token') !== null;
  }

  /**
   * Deauthenticate a user. Remove a token from Local Storage.
   *
   */
  static deauthenticateUser() {
    localStorage.removeItem('token');
  }

  /**
   * Get a token value.
   *
   * @returns {string}
   */

  static getToken() {
    return localStorage.getItem('token');
  }
}

export default Auth;

loginForm.jsx

import React, {PropTypes} from 'react';
import {Link} from 'react-router';
import {Card, CardText} from 'material-ui/Card';
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';

const LoginForm = ({
  locales,
  onSubmit,
  onChange,
  errors,
  successMessage,
  user
}) => (
  <Card className="container">
    <form action="/" onSubmit={onSubmit}>
      <h2 className="card-heading">{locales.connect_to_your_account}</h2>

      {successMessage && <p className="success-message">{successMessage}</p>}
      {errors.summary && <p className="error-message">{errors.summary}</p>}

      <div className="field-line">
        <TextField
          floatingLabelText={locales.email}
          name="email"
          errorText={errors.email}
          onChange={onChange}
          value={user.email}
        />
      </div>

      <div className="field-line">
        <TextField
          floatingLabelText={locales.password}
          type="password"
          name="password"
          onChange={onChange}
          errorText={errors.password}
          value={user.password}
        />
      </div>

      <div className="button-line">
        <RaisedButton type="submit" label={locales.log_in} primary/>
      </div>

      <CardText>{locales.dont_have_account_yet} <Link to={'/request-account'}>{locales.request_one}</Link>.</CardText>
    </form>
  </Card>
);

LoginForm.propTypes = {
  locales       : PropTypes.object.isRequired,
  onSubmit      : PropTypes.func.isRequired,
  onChange      : PropTypes.func.isRequired,
  errors        : PropTypes.object.isRequired,
  successMessage: PropTypes.string.isRequired,
  user          : PropTypes.object.isRequired
};

export default LoginForm;

loginPage.jsx

import React, {PropTypes} from 'react';
import Auth from '../modules/Auth';
import LoginForm from '../components/LoginForm.jsx';

class LoginPage extends React.Component {

  /**
   * Class constructor.
   */
  constructor(props, context) {
    super(props, context);

    const storedMessage = localStorage.getItem('successMessage');
    let successMessage  = '';

    if (storedMessage) {
      successMessage = storedMessage;
      localStorage.removeItem('successMessage');
    }

    // set the initial component state
    this.state = {
      locales: {},
      errors : {},
      successMessage,
      user   : {
        email   : '',
        password: '',
      },
    };

    this.processForm = this.processForm.bind(this);
    this.changeUser  = this.changeUser.bind(this);
  }

  // Load translations via an Api Rest
  componentDidMount() {
    const data = {
      connect_to_your_account: {},
      log_in                 : {},
      email                  : {},
      password               : {},
      dont_have_account_yet  : {},
      request_one            : {},
    };
    const xhr  = new XMLHttpRequest();
    xhr.open('post', '/app_test.php/api/fr/translations');
    xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');

    xhr.responseType = 'json';
    xhr.addEventListener('load', () => {
      if (xhr.status === 200) {
        this.setState({
          locales: xhr.response,
        });
      }
    });
    xhr.send(JSON.stringify(data));
  }

  /**
   * Process the form.
   *
   * @param {object} event - the JavaScript event object
   */
  processForm(event) {
    // prevent default action. in this case, action is the form submission event
    event.preventDefault();

    // create a base64 encoded string
    const credentials = window.btoa(`${this.state.user.email}:${this.state.user.password}`);

    // create an AJAX request
    const xhr           = new XMLHttpRequest();
    xhr.withCredentials = true;
    xhr.open('post', '/app_test.php/api/fr/tokens');
    xhr.setRequestHeader('authorization', `Basic ${credentials}`);

    xhr.responseType = 'json';
    xhr.addEventListener('load', () => {
      if (xhr.status === 201) {
        // success

        // change the component-container state
        this.setState({
          errors: {}
        });

        // save the token
        Auth.authenticateUser(xhr.response.token);

        // change the current URL to /
        this.context.router.replace('/');
      } else {
        // failure

        // change the component state
        const errors   = xhr.response.errors ? xhr.response.errors : {};
        errors.summary = xhr.response.message;

        this.setState({
          errors
        });
      }
    });
    xhr.send(null);
  }

  /**
   * Change the user object.
   *
   * @param {object} event - the JavaScript event object
   */
  changeUser(event) {
    const field = event.target.name;
    const user  = this.state.user;
    user[field] = event.target.value;

    this.setState({
      user
    });
  }

  /**
   * Render the component.
   */
  render() {
    return (
      <LoginForm
        locales={this.state.locales}
        onSubmit={this.processForm}
        onChange={this.changeUser}
        errors={this.state.errors}
        successMessage={this.state.successMessage}
        user={this.state.user}
      />
    );
  }

}

LoginPage.contextTypes = {
  router: PropTypes.object.isRequired
};

export default LoginPage;

routes.js

import Basepage from './containers/BasePage.jsx';
import LoginPage from './containers/LoginPage.jsx';
import Auth from './modules/Auth';

const routes = {
  // base component (wrapper for the whole application).
  component  : Basepage,
  childRoutes: [

    {
      path        : '/',
      getComponent: (location, callback) => {
        if (Auth.isUserAuthenticated()) {
          callback(null, DashboardPage);
        } else {
          callback(null, LoginPage);
        }
      }
    },

    {
      path     : '/login',
      component: LoginPage
    },

    {
      path   : '/logout',
      onEnter: (nextState, replace) => {
        Auth.deauthenticateUser();

        // change the current URL to /
        replace('/');
      }
    }

  ]
};

export default routes;

index.js(接入点)

import React from 'react';
import ReactDom from 'react-dom';
import injectTapEventPlugin from 'react-tap-event-plugin';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import {browserHistory, Router} from 'react-router';
import routes from './routes.js';

import '../styles/main.scss';

// remove tap delay, essential for MaterialUI to work properly
injectTapEventPlugin();

ReactDom.render((
  <MuiThemeProvider muiTheme={getMuiTheme()}>
    <Router history={browserHistory} routes={routes}/>
  </MuiThemeProvider>), document.getElementById('app')
);

我尝试发送给视图的变量是通过Api Rest检索的翻译文本(翻译由后端管理)

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

我终于找到了一个工作场所,不知道它是否是最佳实践:

label={`${myVariable}`}

答案 1 :(得分:0)

您可以尝试使用defaultPropsmyVariable可能会在第一次渲染时undefined

LoginForm.defaultProps= {
    myVariable: "",
};