警告:propType 失败:在 `SignUp` 中未指定必需的 prop `emailExists`
Warning: Failed propType: Required prop `emailExists` was not specified in `SignUp`
收到这些警告:
Warning: Failed propType: Required prop emailExists
was not specified in SignUp
Warning: Failed propType: Required prop onEmailChange
was not specified in SignUp
emailExists prop 和 onEmailChange prop 未在 components/SignUp.js[=43= 中指定].我猜 mapStateToProps 和 mapDispatchToProps 在 [=53= 中传递到 connect() .js 没有将 props 注入 components/SignUp.js 由于一些错误配置。
index.js:
import React from 'react'
import {render} from 'react-dom'
import {Provider} from 'react-redux'
import {createStore, applyMiddleware} from 'redux'
import {Router, Route, IndexRoute, browserHistory} from 'react-router'
import { syncHistoryWithStore } from 'react-router-redux'
import createLogger from 'redux-logger'
import thunkMiddleware from 'redux-thunk'
import donrollApp from './reducers'
import App from './components/LoginApp'
import Login from './components/Login'
import SignUp from './components/SignUp'
const loggerMiddleware = createLogger()
let store = createStore(donrollApp, applyMiddleware(thunkMiddleware, loggerMiddleware))
const history = syncHistoryWithStore(browserHistory, store)
render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={Login}/>
<Route path="signup" component={SignUp}/>
<Route path="*" component={Login}/>
</Route>
</Router>
</Provider>,
document.getElementById('root')
);
containers/SignUp.js:
import { connect } from 'react-redux'
import SignUp from '../components/SignUp'
import { fetchEmailExists } from '../actions'
const mapStateToProps = (state, ownProps) => {
return {
emailExists: state.SignUp.emailExists
}
}
const mapDispatchToProps = (dispatch) => {
return {
onEmailChange: (email) => {
dispatch(fetchEmailExists(email))
}
}
}
const SignUpContainer = connect(
mapStateToProps,
mapDispatchToProps
)(SignUp)
export default SignUpContainer
reducers/SignUp.js:
import Immutable from 'immutable'
const SignUp = (state={emailExists:false, isCheckingEmail: false}, action) => {
let newState = Immutable.Record(state);
switch (action.type) {
case 'CHECK_EMAIL_EXISTS_REQUEST':
return (new newState({isCheckingEmail:true})).toJS();
case 'CHECK_EMAIL_EXISTS_RESPONSE':
return (new newState({emailExists: action.emailExists})).toJS();
default:
return state
}
}
export default SignUp
reducers/index.js:
import { combineReducers } from 'redux'
import SignUp from './SignUp'
import { routerReducer } from 'react-router-redux'
const donrollApp = combineReducers({
SignUp,
routing: routerReducer
})
export default donrollApp
components/SignUp.js:
import React, { PropTypes } from 'react'
import {Link} from 'react-router'
const SignUp = ({emailExists, onEmailChange}) => {
let signupData = {
firstname:{},
lastname:{},
email:{},
username:{},
password:{},
confirmPassword:{}
}
return (
<div>
<form>
<div className="form-group row">
<h4 className="col-sm-12">Sign Up</h4>
</div>
<div className="form-group row">
<label htmlFor="inputFirstname3" className="col-sm-3 col-form-label">Firstname</label>
<div className="col-sm-9">
<input type="text" className="form-control" id="inputFirstname3" placeholder="Firstname" ref={node=>{signupData.firstname=node;}} />
</div>
</div>
<div className="form-group row">
<label htmlFor="inputLastname3" className="col-sm-3 col-form-label">Lastname</label>
<div className="col-sm-9">
<input type="text" className="form-control" id="inputLastname3" placeholder="Lastname" ref={node=>{signupData.lastname=node;}}/>
</div>
</div>
<div className={emailExists?'form-group row has-danger':'form-group row'}>
<label htmlFor="inputEmail3" className="col-sm-3 col-form-label">Email</label>
<div className="col-sm-9">
<input type="email" onBlur={e=>onEmailChange(signupData.email.value)} className="form-control" id="inputEmail3" placeholder="Email" ref={node=>{signupData.email=node;}}/>
{emailExists?<div className="form-control-feedback">Shit, that email's taken. Try another?</div>:null}
</div>
</div>
<div className="form-group row">
<label htmlFor="inputUsername3" className="col-sm-3 col-form-label">Username</label>
<div className="col-sm-9">
<input type="text" className="form-control" id="inputUsername3" placeholder="Username" ref={node=>{signupData.username=node;}}/>
</div>
</div>
<div className="form-group row">
<label htmlFor="inputPassword3" className="col-sm-3 col-form-label">Password</label>
<div className="col-sm-9">
<input type="password" className="form-control" id="inputPassword3" placeholder="Password" ref={node=>{signupData.password=node;}}/>
</div>
</div>
<div className="form-group row">
<label htmlFor="inputConfirmPassword3" className="col-sm-3 col-form-label">Confirm Password</label>
<div className="col-sm-9">
<input type="password" className="form-control" id="inputConfirmPassword3"
placeholder="Confirm Password" ref={node=>{signupData.confirmPassword=node;}}/>
</div>
</div>
<div className="form-group row">
<div className="offset-sm-3 col-sm-9">
<button type="submit" className="btn btn-primary">Sign Up</button>
{" "}
<Link to="/">Login</Link>
</div>
</div>
</form>
</div>
)
}
SignUp.propTypes = {
emailExists: PropTypes.bool.isRequired,
onEmailChange: PropTypes.func.isRequired
}
export default SignUp
问题是,我在 index.js。因此 index.js 中的行 import SignUp from './components/SignUp'
变为 import SignUp from './containers/SignUp'
。因为,containers 围绕着 components 并将 Redux states 映射到 React props 并将 Redux dispatches 映射到 React prop callbacks 以及所有 props在需要时注入 components。 containers 订阅 Redux store 并将新的 props 注入 components 当新的订阅信号到达并且 组件 使用新的 props 更新它们自己。 components 调用 callback props 来更改数据并反过来使 containers 调度 动作。有关详细信息,我们有文档 here.
收到这些警告:
Warning: Failed propType: Required prop
emailExists
was not specified inSignUp
Warning: Failed propType: Required prop
onEmailChange
was not specified inSignUp
emailExists prop 和 onEmailChange prop 未在 components/SignUp.js[=43= 中指定].我猜 mapStateToProps 和 mapDispatchToProps 在 [=53= 中传递到 connect() .js 没有将 props 注入 components/SignUp.js 由于一些错误配置。
index.js:
import React from 'react'
import {render} from 'react-dom'
import {Provider} from 'react-redux'
import {createStore, applyMiddleware} from 'redux'
import {Router, Route, IndexRoute, browserHistory} from 'react-router'
import { syncHistoryWithStore } from 'react-router-redux'
import createLogger from 'redux-logger'
import thunkMiddleware from 'redux-thunk'
import donrollApp from './reducers'
import App from './components/LoginApp'
import Login from './components/Login'
import SignUp from './components/SignUp'
const loggerMiddleware = createLogger()
let store = createStore(donrollApp, applyMiddleware(thunkMiddleware, loggerMiddleware))
const history = syncHistoryWithStore(browserHistory, store)
render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={Login}/>
<Route path="signup" component={SignUp}/>
<Route path="*" component={Login}/>
</Route>
</Router>
</Provider>,
document.getElementById('root')
);
containers/SignUp.js:
import { connect } from 'react-redux'
import SignUp from '../components/SignUp'
import { fetchEmailExists } from '../actions'
const mapStateToProps = (state, ownProps) => {
return {
emailExists: state.SignUp.emailExists
}
}
const mapDispatchToProps = (dispatch) => {
return {
onEmailChange: (email) => {
dispatch(fetchEmailExists(email))
}
}
}
const SignUpContainer = connect(
mapStateToProps,
mapDispatchToProps
)(SignUp)
export default SignUpContainer
reducers/SignUp.js:
import Immutable from 'immutable'
const SignUp = (state={emailExists:false, isCheckingEmail: false}, action) => {
let newState = Immutable.Record(state);
switch (action.type) {
case 'CHECK_EMAIL_EXISTS_REQUEST':
return (new newState({isCheckingEmail:true})).toJS();
case 'CHECK_EMAIL_EXISTS_RESPONSE':
return (new newState({emailExists: action.emailExists})).toJS();
default:
return state
}
}
export default SignUp
reducers/index.js:
import { combineReducers } from 'redux'
import SignUp from './SignUp'
import { routerReducer } from 'react-router-redux'
const donrollApp = combineReducers({
SignUp,
routing: routerReducer
})
export default donrollApp
components/SignUp.js:
import React, { PropTypes } from 'react'
import {Link} from 'react-router'
const SignUp = ({emailExists, onEmailChange}) => {
let signupData = {
firstname:{},
lastname:{},
email:{},
username:{},
password:{},
confirmPassword:{}
}
return (
<div>
<form>
<div className="form-group row">
<h4 className="col-sm-12">Sign Up</h4>
</div>
<div className="form-group row">
<label htmlFor="inputFirstname3" className="col-sm-3 col-form-label">Firstname</label>
<div className="col-sm-9">
<input type="text" className="form-control" id="inputFirstname3" placeholder="Firstname" ref={node=>{signupData.firstname=node;}} />
</div>
</div>
<div className="form-group row">
<label htmlFor="inputLastname3" className="col-sm-3 col-form-label">Lastname</label>
<div className="col-sm-9">
<input type="text" className="form-control" id="inputLastname3" placeholder="Lastname" ref={node=>{signupData.lastname=node;}}/>
</div>
</div>
<div className={emailExists?'form-group row has-danger':'form-group row'}>
<label htmlFor="inputEmail3" className="col-sm-3 col-form-label">Email</label>
<div className="col-sm-9">
<input type="email" onBlur={e=>onEmailChange(signupData.email.value)} className="form-control" id="inputEmail3" placeholder="Email" ref={node=>{signupData.email=node;}}/>
{emailExists?<div className="form-control-feedback">Shit, that email's taken. Try another?</div>:null}
</div>
</div>
<div className="form-group row">
<label htmlFor="inputUsername3" className="col-sm-3 col-form-label">Username</label>
<div className="col-sm-9">
<input type="text" className="form-control" id="inputUsername3" placeholder="Username" ref={node=>{signupData.username=node;}}/>
</div>
</div>
<div className="form-group row">
<label htmlFor="inputPassword3" className="col-sm-3 col-form-label">Password</label>
<div className="col-sm-9">
<input type="password" className="form-control" id="inputPassword3" placeholder="Password" ref={node=>{signupData.password=node;}}/>
</div>
</div>
<div className="form-group row">
<label htmlFor="inputConfirmPassword3" className="col-sm-3 col-form-label">Confirm Password</label>
<div className="col-sm-9">
<input type="password" className="form-control" id="inputConfirmPassword3"
placeholder="Confirm Password" ref={node=>{signupData.confirmPassword=node;}}/>
</div>
</div>
<div className="form-group row">
<div className="offset-sm-3 col-sm-9">
<button type="submit" className="btn btn-primary">Sign Up</button>
{" "}
<Link to="/">Login</Link>
</div>
</div>
</form>
</div>
)
}
SignUp.propTypes = {
emailExists: PropTypes.bool.isRequired,
onEmailChange: PropTypes.func.isRequired
}
export default SignUp
问题是,我在 index.js。因此 index.js 中的行 import SignUp from './components/SignUp'
变为 import SignUp from './containers/SignUp'
。因为,containers 围绕着 components 并将 Redux states 映射到 React props 并将 Redux dispatches 映射到 React prop callbacks 以及所有 props在需要时注入 components。 containers 订阅 Redux store 并将新的 props 注入 components 当新的订阅信号到达并且 组件 使用新的 props 更新它们自己。 components 调用 callback props 来更改数据并反过来使 containers 调度 动作。有关详细信息,我们有文档 here.