2016-09-16 13 views
1

私はリアクションとマテリアルでarroundを再生していますが、マテリアルUIコンポーネントのラベルに変数を渡す方法はありますか?編集Material UI RaisedButton Labelで変数を許可する

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

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

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

export default LoginForm; 

しかし、ラベルはブラウザ(クロム)で正しく表示されても、コンソールは私にこの警告を表示:ここで

は私のコードです 一部のデバッグ後、ビューが複数回(少なくとも4回)表示され、1番目のレンダリングではmyVariableが未定義になります。

ここで、コンポーネントが何回連続してレンダリングされるのか、第1レンダリングで変数が定義されない理由を管理する必要があります。

ここに私のコード。

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; 

(ACCESポイント)

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経由で残りのテキストを翻訳検索されindex.js(翻訳バックエンドによって管理されます)

ありがとうございました。

+0

にあなたのレンダリングにundefinedかもしれませんコードは有効ではありません。私が知っている限り、 'primary = {true}'でなければなりません。 'myVariable'の内容は何ですか? –

+0

プライマリ= {true}を設定するコードが修正され、何も変更されません。 myVariableはランダムな文字列です。 –

+0

私が知っている限り、 'prop = {true}'と 'prop'だけは同等であり、どちらも有効です。 – Waiski

答えて

0

私は最終的にそのベストプラクティスかどうworkarroundは、知りませんが見つかりました:あなたがdefaultPropsで試すことができ

label={`${myVariable}`} 
+0

それはありません。単に 'label =" myLabel "'を実行すると、エラーはなくなったか? –

+0

はい、 'label =" myLabel "'を使用すると、エラーはなくなりますが、テキストを直接設定したくないので、可変テキストが必要です。どのように私は最高のプラチナを使用してそれを行うことができますか?ありがとう。 –

+0

私はこれを考えました。あなたが答えているのは、propTypeという文字列の要件を満たすことだからです。最初の 'render'で' myVariable'が 'undefined'になることはありますか?あなたは本当に完全なコードを追加する必要があります! –

0

myVariableは最初

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

はい、これはel solo loboさんのようです。しかし、今私は多くのレンダリングがある理由を知りたい(少なくともログインページに4)。元の質問に完全なコードを追加しました。再度、感謝します。 –

関連する問題