我正在玩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检索的翻译文本(翻译由后端管理)
感谢您的帮助。
答案 0 :(得分:0)
我终于找到了一个工作场所,不知道它是否是最佳实践:
label={`${myVariable}`}
答案 1 :(得分:0)
您可以尝试使用defaultProps,myVariable
可能会在第一次渲染时undefined
LoginForm.defaultProps= {
myVariable: "",
};