title: Allowing variable in material UI RaisedButton Label
body: <p>I'm playing arround with React and Material and I'm wandering how I can pass a variable in a Material UI component label ?</p>
  
  <p>Here is my code :</p>
  
  <pre><code>const LoginForm = ({
      myVariable
  }) =&gt; (
      {/*....*/}
      &lt;RaisedButton type="submit" label={myVariable} primary/&gt;
      {/*....*/}
  );
  
  LoginForm.propTypes = {
      myVariable : PropTypes.string.isRequired
  };
  
  export default LoginForm;
  </code></pre>
  
  <p>But, even if the label is displayed correctly in the browser (chromium), the console show me this warning : </p>
  
  <pre><code>warning.js:36 Warning: Failed prop type: Required prop label or children or icon was not specified in RaisedButton.
  </code></pre>
  
  <p><strong>Edit:</strong>
  After some debugging, it occurs that the view is rendered several times (at least 4 times ???) and that in the 1st render, myVariable is undefined.</p>
  
  <p>So, now, I have to manage why the component is rendered sevral times and why in the 1st render, variables are undefined.</p>
  
  <p>So here my code.</p>
  
  <p><strong>Base.jsx</strong></p>
  
  <pre><code>import React, {PropTypes} from 'react';
  import {Link, IndexLink} from 'react-router';
  
  const Base = ({
    children
  }) =&gt; (
    &lt;div&gt;
      &lt;div className="top-bar"&gt;
      {children}
    &lt;/div&gt;
  );
  
  Base.propTypes = {
    children: PropTypes.object.isRequired
  };
  
  export default Base;
  </code></pre>
  
  <p><strong>Auth.js</strong></p>
  
  <pre><code>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;
  </code></pre>
  
  <p><strong>loginForm.jsx</strong></p>
  
  <pre><code>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
  }) =&gt; (
    &lt;Card className="container"&gt;
      &lt;form action="/" onSubmit={onSubmit}&gt;
        &lt;h2 className="card-heading"&gt;{locales.connect_to_your_account}&lt;/h2&gt;
  
        {successMessage &amp;&amp; &lt;p className="success-message"&gt;{successMessage}&lt;/p&gt;}
        {errors.summary &amp;&amp; &lt;p className="error-message"&gt;{errors.summary}&lt;/p&gt;}
  
        &lt;div className="field-line"&gt;
          &lt;TextField
            floatingLabelText={locales.email}
            name="email"
            errorText={errors.email}
            onChange={onChange}
            value={user.email}
          /&gt;
        &lt;/div&gt;
  
        &lt;div className="field-line"&gt;
          &lt;TextField
            floatingLabelText={locales.password}
            type="password"
            name="password"
            onChange={onChange}
            errorText={errors.password}
            value={user.password}
          /&gt;
        &lt;/div&gt;
  
        &lt;div className="button-line"&gt;
          &lt;RaisedButton type="submit" label={locales.log_in} primary/&gt;
        &lt;/div&gt;
  
        &lt;CardText&gt;{locales.dont_have_account_yet} &lt;Link to={'/request-account'}&gt;{locales.request_one}&lt;/Link&gt;.&lt;/CardText&gt;
      &lt;/form&gt;
    &lt;/Card&gt;
  );
  
  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;
  </code></pre>
  
  <p>loginPage.jsx</p>
  
  <pre><code>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', () =&gt; {
        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', () =&gt; {
        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 (
        &lt;LoginForm
          locales={this.state.locales}
          onSubmit={this.processForm}
          onChange={this.changeUser}
          errors={this.state.errors}
          successMessage={this.state.successMessage}
          user={this.state.user}
        /&gt;
      );
    }
  
  }
  
  LoginPage.contextTypes = {
    router: PropTypes.object.isRequired
  };
  
  export default LoginPage;
  </code></pre>
  
  <p>routes.js</p>
  
  <pre><code>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) =&gt; {
          if (Auth.isUserAuthenticated()) {
            callback(null, DashboardPage);
          } else {
            callback(null, LoginPage);
          }
        }
      },
  
      {
        path     : '/login',
        component: LoginPage
      },
  
      {
        path   : '/logout',
        onEnter: (nextState, replace) =&gt; {
          Auth.deauthenticateUser();
  
          // change the current URL to /
          replace('/');
        }
      }
  
    ]
  };
  
  export default routes;
  </code></pre>
  
  <p>index.js (acces point)</p>
  
  <pre><code>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((
    &lt;MuiThemeProvider muiTheme={getMuiTheme()}&gt;
      &lt;Router history={browserHistory} routes={routes}/&gt;
    &lt;/MuiThemeProvider&gt;), document.getElementById('app')
  );
  </code></pre>
  
  <p>The variables I try to send to the views are translated text retrieved via an Api Rest (translations is managed by the backend)</p>
  
  <p>Thanks for any help.</p>