为什么使用重复的嵌套键更新 Redux 存储?
Why is the Redux store being updated with a duplicate nested key?
我从 React 和 Redux 开始,所以我将一个组件连接到 Redux 商店,我得到了这个组件,它应该是一个非常简单的登录:
import React, { Component } from 'react';
import { findDOMNode } from "react-dom";
import RaisedButton from 'material-ui/lib/raised-button';
import TextField from 'material-ui/lib/text-field';
import { connect } from 'react-redux';
import { loginRequest, loginSuccess, loginFailure } from '../actions';
import { browserHistory } from 'react-router';
class LoginForm extends Component {
componentDidMount() {
console.log(console.log(JSON.stringify(this.props,null,2)));
}
readyToSubmit() {
}
onSubmit(e) {
e && e.preventDefault();
let emailInput = findDOMNode(this.refs.emailInput).querySelector("input").value;
let passwordInput = findDOMNode(this.refs.passwordInput).querySelector("input").value;
if (emailInput.trim().length && passwordInput.trim().length) {
if (emailInput.startsWith('hello')) {
this.props.loginSuccess(emailInput);
} else {
console.log(emailInput);
this.props.loginFailure(emailInput);
}
}
}
render() {
let disabled = !!this.props.login.waiting || !!this.props.ready;
return (
<form onSubmit={::this.onSubmit}>
<div>
<TextField hint="E-mail" floatingLabelText="E-mail" ref="emailInput" onChange={::this.readyToSubmit}></TextField><br/>
</div>
<div>
<TextField hint="Contraseña" floatingLabelText="Contraseña" type="password" ref="passwordInput" onChange={::this.readyToSubmit}></TextField><br/><br/>
</div>
<div>
<RaisedButton type="submit" label="Acceder" primary={true} disabled={disabled} onClick={::this.onSubmit}/>
</div>
</form>
);
}
}
export default connect(
state => {
return {
login: state.login
}
},
{
loginSuccess: loginSuccess,
loginFailure: loginFailure,
loginRequest: loginRequest
})(LoginForm);
这些是操作:
export const loginSuccess = (email) => {
return {type: 'LOGIN_SUCCESS', email: email };
}
export const loginFailure = (email) => {
return {type: 'LOGIN_FAILURE', email: email };
}
export const loginRequest = (email) => {
return {type: 'LOGIN_REQUEST', email: email};
}
这些是我的减速器:
const login = (state = {}, action) => {
switch (action.type) {
case 'LOGIN_REQUEST':
return {
...state.login,
login: {
waiting: true,
email: action.email
}
};
break;
case 'LOGIN_SUCCESS':
return {
...state.login,
login: {
waiting: false,
email: action.email,
},
auth: {
token: state.token
}
};
break;
case 'LOGIN_FAILURE':
return {
...state.login,
login: {
waiting: false,
email: action.email,
errors: action.errors
}
};
break;
default:
return {
...state.login,
login: {
ready: false
}
};
}
}
export default login
所以,我注意到的第一个奇怪的东西是 componentDidMount
日志:
{
"login": {
"login": {
"ready": false
}
}
}
所以我需要一些帮助:
- 我不明白为什么要这样嵌套 (
login.login
).
- 我想仅在密码和电子邮件字段都已填写时禁用该按钮。
- 我知道 Redux 会避免 我使用 React 的
state
,并且连接函数将组件属性的一些存储属性和一些调度程序绑定到属性也是..但是我怎样才能轻松访问字段、按钮等值作为道具的一部分。
- 我怎样才能确保在我的减速器上进行真正的深度合并?
我认为这很可能是你的减速器,而不是这个:
case 'LOGIN_REQUEST':
return {
...state.login,
login: {
waiting: true,
email: action.email
}
};
break;
试试这个:
case 'LOGIN_REQUEST':
return {
...state, <-- removed the .login from here
login: {
waiting: true,
email: action.email
}
};
break;
或者:
case 'LOGIN_REQUEST':
return {
...state.login,
//<-- removed the login key from the object you add to state.login
waiting: true,
email: action.email
};
break;
如果有帮助请告诉我们:)
写下:
state => {return state.login}
而不是
export default connect(
state => {
return {
login: state.login
}
我从 React 和 Redux 开始,所以我将一个组件连接到 Redux 商店,我得到了这个组件,它应该是一个非常简单的登录:
import React, { Component } from 'react';
import { findDOMNode } from "react-dom";
import RaisedButton from 'material-ui/lib/raised-button';
import TextField from 'material-ui/lib/text-field';
import { connect } from 'react-redux';
import { loginRequest, loginSuccess, loginFailure } from '../actions';
import { browserHistory } from 'react-router';
class LoginForm extends Component {
componentDidMount() {
console.log(console.log(JSON.stringify(this.props,null,2)));
}
readyToSubmit() {
}
onSubmit(e) {
e && e.preventDefault();
let emailInput = findDOMNode(this.refs.emailInput).querySelector("input").value;
let passwordInput = findDOMNode(this.refs.passwordInput).querySelector("input").value;
if (emailInput.trim().length && passwordInput.trim().length) {
if (emailInput.startsWith('hello')) {
this.props.loginSuccess(emailInput);
} else {
console.log(emailInput);
this.props.loginFailure(emailInput);
}
}
}
render() {
let disabled = !!this.props.login.waiting || !!this.props.ready;
return (
<form onSubmit={::this.onSubmit}>
<div>
<TextField hint="E-mail" floatingLabelText="E-mail" ref="emailInput" onChange={::this.readyToSubmit}></TextField><br/>
</div>
<div>
<TextField hint="Contraseña" floatingLabelText="Contraseña" type="password" ref="passwordInput" onChange={::this.readyToSubmit}></TextField><br/><br/>
</div>
<div>
<RaisedButton type="submit" label="Acceder" primary={true} disabled={disabled} onClick={::this.onSubmit}/>
</div>
</form>
);
}
}
export default connect(
state => {
return {
login: state.login
}
},
{
loginSuccess: loginSuccess,
loginFailure: loginFailure,
loginRequest: loginRequest
})(LoginForm);
这些是操作:
export const loginSuccess = (email) => {
return {type: 'LOGIN_SUCCESS', email: email };
}
export const loginFailure = (email) => {
return {type: 'LOGIN_FAILURE', email: email };
}
export const loginRequest = (email) => {
return {type: 'LOGIN_REQUEST', email: email};
}
这些是我的减速器:
const login = (state = {}, action) => {
switch (action.type) {
case 'LOGIN_REQUEST':
return {
...state.login,
login: {
waiting: true,
email: action.email
}
};
break;
case 'LOGIN_SUCCESS':
return {
...state.login,
login: {
waiting: false,
email: action.email,
},
auth: {
token: state.token
}
};
break;
case 'LOGIN_FAILURE':
return {
...state.login,
login: {
waiting: false,
email: action.email,
errors: action.errors
}
};
break;
default:
return {
...state.login,
login: {
ready: false
}
};
}
}
export default login
所以,我注意到的第一个奇怪的东西是 componentDidMount
日志:
{
"login": {
"login": {
"ready": false
}
}
}
所以我需要一些帮助:
- 我不明白为什么要这样嵌套 (
login.login
). - 我想仅在密码和电子邮件字段都已填写时禁用该按钮。
- 我知道 Redux 会避免 我使用 React 的
state
,并且连接函数将组件属性的一些存储属性和一些调度程序绑定到属性也是..但是我怎样才能轻松访问字段、按钮等值作为道具的一部分。 - 我怎样才能确保在我的减速器上进行真正的深度合并?
我认为这很可能是你的减速器,而不是这个:
case 'LOGIN_REQUEST':
return {
...state.login,
login: {
waiting: true,
email: action.email
}
};
break;
试试这个:
case 'LOGIN_REQUEST':
return {
...state, <-- removed the .login from here
login: {
waiting: true,
email: action.email
}
};
break;
或者:
case 'LOGIN_REQUEST':
return {
...state.login,
//<-- removed the login key from the object you add to state.login
waiting: true,
email: action.email
};
break;
如果有帮助请告诉我们:)
写下:
state => {return state.login}
而不是
export default connect(
state => {
return {
login: state.login
}