我正在尝试仅显示我从状态映射到容器组件的props的查询数组的一部分(使用mapStateToProps)。
为此,我使用spread运算符Array.slice,然后迭代子数组以创建组件。在我的应用程序上,我可以成功地显示子数组和完整数组的各个页面,但每当我触发一个操作来重新排列或替换数组中的元素时,我总是在将相应的操作发送给我之后得到此错误减速器:
未捕获的不变违规:在路径
querys.0.submit_time._isValid
中的调度之间检测到状态突变。这可能会导致错误的行为。
我只在第一次点击时收到此错误。如果我显示整个数组,也不会发生此错误。在此数组中,每个元素(查询)都具有时刻1属性。上面的错误被抛出在应用程序上没有显示的第一个元素上(在这种情况下,查询0被跳过。如果我显示查询0-9,那么错误将是查询10)。由于submit_time被认为是变异的,我使用了moment.clone()来深度复制它,但仍然会出错。有谁知道如何显示数组切片并避免此错误?
编辑:
这是我的组件,动作和减速器的简化代码。我的组件最初从redux store传递查询作为prop。然后,它将此数组的一个片段传递给子组件,该组件为每个元素创建一个tr(通过迭代)。在应用程序上,您可以通过切换单选按钮来触发onSortChange事件处理程序。这会触发SORT_QUERIES_BY_FIELD操作,这会导致queryReducer使用List.sort对数组进行排序。当我第一次触发onSortChange操作并且在调度SORT_QUERIES_BY_FIELD操作之前发生错误:
组件:
import React, {PropTypes} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import moment from 'moment';
import * as queryActions from '../../actions/queryActions';
import QueryList from './QueryList';
import RadioGroup from 'react-radio';
class TroubleshootPage extends React.Component {
constructor(props, context) {
super(props, context);
this.onSortChange = this.onSortChange.bind(this);
this.state = {querys: [...this.props.querys]};
}
componentWillReceiveProps(nextProps) {
this.setState({querys: nextProps.querys});
}
onSortChange(value, event) {
this.props.actions.sortQueriesByField(value);
}
render() {
const {querys, radioGroupValue} = this.state;
let subList = [...querys].slice(0,9);
return (
<div>
<RadioGroup name="sorts" defaultValue={null} onChange={this.onSortChange.bind(this)}>
<input type="radio" value="total_elapsed_time" />Elapsed Time
</RadioGroup>
<QueryList selectedQuery={this.selectedQuery}
selectedQueryStep={this.selectedQueryStep}
querys={subList} />
</div>
);
}
}
TroubleshootPage.propTypes = {
querys: PropTypes.array.isRequired,
actions: PropTypes.object.isRequired
};
function mapStateToProps(state, ownProps) {
return {querys: state.querys};
}
function mapDispatchToProps(dispatch) {
return {actions: bindActionCreators(queryActions, dispatch)};
}
export default connect(mapStateToProps, mapDispatchToProp)(TroubleshootPage);
动作:
import * as types from './actionTypes';
import queryApi from '../api/mockQueryApi';
export function sortQueriesByField(field) {
return { type: types.SORT_QUERIES_BY_FIELD, field};
}
减速机:
import * as types from '../actions/actionTypes';
import initialState from './initialState';
export default function queryReducer(state = initialState.querys, action) {
switch(action.type) {
case types.SORT_QUERIES_BY_FIELD:
let {field} = action;
var querys = [...state];
querys.sort(function(a,b) {return a[field]-b[field]})
return querys;
default:
return state;
}
}
答案 0 :(得分:0)
我遇到了同样的问题,但是当我在我的类之外创建一个变量并更新变量和状态时,终于让它工作了。这是代码。它非常敏感,我知道这是一种反模式,但它有效!
import React, {PropTypes} from 'react';
import {connect} from 'react-redux';
import { Row, Col } from 'react-bootstrap';
import {bindActionCreators} from 'redux';
import DatePicker from 'react-datepicker';
import * as actions from '../actions/checkoutActions';
import moment from 'moment';
import 'react-datepicker/dist/react-datepicker.css';
let date = moment();
class AppointmentPage extends React.Component{
constructor(props, context){
super(props, context);
this.createAppt = this.createAppt.bind(this);
this.updateDate = this.updateDate.bind(this);
this.updateTime = this.updateTime.bind(this);
this.printTimeRange = this.printTimeRange.bind(this);
}
printTimeRange(appt){
let active = "";
if(this.props.apptTime === appt)
active = "active";
return (
<li key={appt} className={"list-group-item appt-item "+active} id={"time_"+appt} onClick={this.updateTime}>
{moment(appt+":00", ["H:mm"]).format("h:mm A")+' - '+moment((appt+1)+":00", ["H:mm"]).format("h:mm A")}
</li>
);
}
updateDate(apptDate){
date = apptDate;
return this.setState({apptDate});
}
updateTime(e){
const id = Number(e.target.id.substring(5));
this.props.actions.updateTime(id);
}
createAppt(e){
e.preventDefault();
this.props.actions.createAppt();
}
render(){
return (
<Row>
<Col md={2}/>
<Col md={8}>
<h2>
Schedule An Appointment
<button className="btn btn-primary pull-right" onClick={this.createAppt}>Make Appointment</button>
</h2><hr/>
<Row>
<Col md={6}>
<DatePicker inline
selected={date}
onChange={this.updateDate} />
</Col>
<Col md={6}>
<ul className="list-group">
{this.props.appointments && this.props.appointments.map(this.printTimeRange)}
</ul>
</Col>
</Row>
</Col>
</Row>
);
}
}
AppointmentPage.propTypes = {
actions: PropTypes.object.isRequired,
user: PropTypes.object.isRequired,
appointments: PropTypes.array,
apptTime: PropTypes.number
};
export default connect(
(s)=>{return {
user:s.user,
appointments:s.checkout.appointments,
apptTime: s.checkout.apptTime
};},
d=>{return {actions:bindActionCreators(actions,d)};}
)(AppointmentPage);
答案 1 :(得分:0)
之前我有同样的问题,在我的情况下,这是由浅拷贝造成的。每当我返回一个新状态时,旧状态也会改变。
我使用了一种棘手的方法来通过JSON.parse(JSON.stringify(temp))
来创建深度克隆来实现它。
您也可以尝试var querys = JSON.parse(JSON.stringify(state));
。
希望它有效。