React-Redux Store中状态变量console.log后显示undefined问题求助
我制作了一个银行账户信息提交表单,点击提交按钮后无法捕获输入值并将其存入Redux store。在constructor中执行console.log(this.props),以及执行console.log(this.props.firstname)、console.log(this.props.lastname)等语句时,控制台均输出undefined,控制台截图如下:

Form.js(表单组件)
import React, { Component } from 'react'; import { connect } from 'react-redux'; import * as action from '../actions/actions'; import './form.css'; class Form extends Component { constructor(props) { super(props) this.setFirstName = this.setFirstName.bind(this); this.setLastName = this.setLastName.bind(this); this.setEmailId = this.setEmailId.bind(this); this.setIban = this.setIban.bind(this); this.setBankName = this.setBankName.bind(this); this.showUser = this.showUser.bind(this); console.log(this.props); } setFirstName(event) { this.props.dispatch(action.setFirstName(event.target.value)); } setLastName(event) { this.props.dispatch(action.setLastName(event.target.value)); } setEmailId(event) { this.props.dispatch(action.setEmailId(event.target.value)); } setIban(event) { this.props.dispatch(action.setIban(event.target.value)); } setBankName(event) { this.props.dispatch(action.setBankName(event.target.value)); } showUser(){ console.log(this.props.firstname); console.log(this.props.lastname); console.log(this.props.emailid); } render(){ return( <div> <div id="center"> <form> <div className="form-group"> <label for="firstname">First Name:</label> <input type="firstname" className="form-control" id="firstname" onChange={this.setFirstName}/> </div> <div className="form-group"> <label for="lastname">Last Name:</label> <input type="lastname" className="form-control" id="lastname" onChange={this.setLastName}/> </div> <div className="form-group"> <label for="email">Email address:</label> <input type="email" className="form-control" id="email" onChange={this.setEmailId}/> </div> <div className="form-group"> <label for="bankacc">IBAN:</label> <div id="deletebank" className="items"> <input type="bankacc" className="form-control" id="bankacc" onChange={this.setIban}/> <button type="button" className="btn btn-default btn-sm"> <span class="glyphicon glyphicon-trash"></span> </button> </div> </div> <div className="form-group"> <label for="bankname">Bank Name:</label> <input type="bankname" className="form-control" id="bankname" onChange={this.setBankName}/> </div> <div className="form-group"> <button type="button" className="btn addbank">+ Add bank account</button> </div> <div className="form-group"> <button type="button" className="btn btn-success" onClick={this.showUser}>Submit</button> </div> </form> </div> </div> ) } } const mapStateToProps = store => { return { firstname: store.firstname, lastname: store.lastname, emailid: store.emailid, iban: store.iban, bankname: store.bankname } } export default connect(mapStateToProps)(Form);
actions.js
export const SET_FIRSTNAME = 'SET_FIRSTNAME'; export const SET_LASTNAME = 'SET_LASTNAME'; export const SET_EMAILID = 'SET_EMAILID'; export const SET_IBAN = 'SET_IBAN'; export const SET_BANKNAME = 'SET_BANKNAME'; export function setFirstName(firstname){ return { type:SET_FIRSTNAME, payLoad:firstname } } export function setLastName(lastname){ return { type:SET_LASTNAME, payLoad:lastname } } export function setEmailId(emailid){ return { type:SET_EMAILID, payLoad:emailid } } export function setIban(iban){ return { type:SET_IBAN, payLoad:iban } } export function setBankName(bankname){ return { type:SET_BANKNAME, payLoad:bankname } }
Reducer.js
const userReducer = (state = { user:{ firstname:'', lastname:'', emailid:'', bankaccounts:{ iban:'', bankname:'' } } }, action) => { switch (action.type) { case 'SET_FIRSTNAME':{ return { ...state, user:{...state.user, firstname: action.payload} } } case 'SET_LASTNAME':{ return { ...state, user:{...state.user, lastname: action.payload} } } case 'SET_EMAILID':{ return { ...state, user:{...state.user, emailid: action.payload} } } case 'SET_IBAN':{ return { ...state, user:{...state.user, iban: action.payload} } } case 'SET_BANKNAME':{ return { ...state, user:{...state.user, bankname: action.payload} } } default: return state; } } export default userReducer;
我看了你的代码和问题描述,这里有几个关键错误导致你无法捕获输入值并在props中获取到正确数据:
1. mapStateToProps 路径错误
你的Redux store的state结构是嵌套在user对象里的,但你在mapStateToProps里直接从store根节点取属性,这肯定拿不到值。修改后的mapStateToProps应该是:
const mapStateToProps = store => { return { firstname: store.user.firstname, lastname: store.user.lastname, emailid: store.user.emailid, iban: store.user.bankaccounts.iban, bankname: store.user.bankaccounts.bankname } }
2. Action Payload 拼写不一致
在actions.js里,你把负载键名写成了payLoad(大写L),但在Reducer.js里却用action.payload(小写l)获取,大小写不匹配导致Reducer无法正确拿到传入的值。统一改成小写的payload:
修改actions.js里的每个action,比如:
export function setFirstName(firstname){ return { type:SET_FIRSTNAME, payload:firstname // 把payLoad改为payload } } // 其他action同理,全部替换payLoad为payload
3. Reducer中IBAN和BankName的存储路径错误
你的初始state里,iban和bankname是在user.bankaccounts下的,但Reducer里修改时直接存在了user对象下,这样会导致state结构混乱,也无法通过正确路径获取。修改对应的case:
case 'SET_IBAN':{ return { ...state, user:{ ...state.user, bankaccounts: { ...state.user.bankaccounts, iban: action.payload } } } } case 'SET_BANKNAME':{ return { ...state, user:{ ...state.user, bankaccounts: { ...state.user.bankaccounts, bankname: action.payload } } } }
4. 额外优化:Input的type属性错误
你的表单里有些input的type设置不合法(比如type="firstname"、type="lastname"),这些不是HTML标准的input类型,建议改成type="text":
<input type="text" className="form-control" id="firstname" onChange={this.setFirstName}/> <input type="text" className="form-control" id="lastname" onChange={this.setLastName}/> <input type="text" className="form-control" id="bankacc" onChange={this.setIban}/> <input type="text" className="form-control" id="bankname" onChange={this.setBankName}/>
完成这些修改后,你应该就能正确捕获输入值并存储到Redux中,this.props里的属性也能拿到对应的值了。
内容的提问来源于stack exchange,提问作者stone rock

