当我在redux商店中更改预算对象的数据时,负责呈现该对象的组件在数据更改时不会重新呈现该组件。
我有一个<Budget />
组件,它会将预算对象包含在属于我的州/商店的预算对象数组中。我的商店有以下形状:
departmentBudgets : {
isFetching : false,
budgets : [ {
department : 'String',
owner : {
name : 'String',
email : 'String',
title : 'String'
},
budget : 'Number'
} ]
}
我希望<Budget />
组件在编辑其中一个属性时重新呈现和更新预算对象的显示。我正在处理的功能是允许用户编辑和更新预算属性。我的redux减速机如下所示:
import * as types from '../constants/actionTypes';
import union from 'lodash/array/union';
import uniq from 'lodash/array/uniq';
const initialState = {
isFetching : false,
budgets : []
};
export default function budgets( state = initialState, action = {} ) {
const { type, payload, meta } = action;
switch ( type ) {
case types.FETCH_CURRENT_BUDGETS:
return Object.assign({}, state, {
isFetching : true
});
case types.RECEIVE_CURRENT_BUDGETS:
return Object.assign({}, state, {
isFetching : false,
budgets : uniq(union(state.budgets, payload), '_id')
});
case types.UPDATE_DEPARTMENT_BUDGET:
const changedIndex = state.budgets.findIndex(( budget ) => {
return budget._id === payload._id;
});
const newBudgets = [ ...state.budgets.slice(0, changedIndex),
Object.assign({}, state.budgets[ changedIndex ], {
budget : payload.budget
}),
...state.budgets.slice(changedIndex + 1) ];
return Object.assign({}, state, {
budgets : newBudgets
});
default:
return state;
}
}
我是否在上面的reducer中正确处理了更新?我相信这不会改变状态对象,但也许不是吗?
我的反应组件树如下所示呈现此数据:
DepartmentBudgetsContainer
DepartmentBudgets
Budget
container元素从数据库中获取当前数据,并使用react-redux将其连接到商店,如下所示:
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { fetchBudgets, updateBudget } from '../../actions/departmentBudget.actions';
import DepartmentBudgets from '../../components/administration/department_budgets/DepartmentBudgets';
const displayName = 'DepartmentBudgetContainer';
const propTypes = {
budgets : PropTypes.object
};
class DepartmentBudgetContainer extends Component {
constructor( props, context ) {
super(props, context);
this.budgetDidchange = this.budgetDidchange.bind(this);
}
componentDidMount() {
let { dispatch } = this.props;
dispatch(fetchBudgets());
}
budgetDidchange( id, budget ) {
let { dispatch } = this.props;
const newBudget = {
_id : id,
budget : budget
};
dispatch(updateBudget(newBudget));
}
render() {
const { budgets } = this.props;
return (
<DepartmentBudgets updateBudget={this.budgetDidchange} budgets={budgets.budgets} />
);
}
}
DepartmentBudgetContainer.displayName = displayName;
DepartmentBudgetContainer.propTypes = propTypes;
function mapStateToProps( state ) {
return {
budgets : state.departmentBudgets.budgets
}
}
export default connect(mapStateToProps)(DepartmentBudgetContainer);
然后,DepartmentBudgets组件负责创建每个预算组件,如下所示:
import React, { Component, PropTypes } from 'react';
import TableComps from '../../../../node_modules/material-ui/lib/table';
import Budget from './Budget';
const Table = TableComps.Table;
const TableHeader = TableComps.TableHeader;
const TableRow = TableComps.TableRow;
const TableHeaderColumn = TableComps.TableHeaderColumn;
const TableBody = TableComps.TableBody;
const TableRowColumn = TableComps.TableRowColumn;
const displayName = 'DepartmentBudgets';
const propTypes = {
budgets : PropTypes.arrayOf(PropTypes.object).isRequired,
updateBudget : PropTypes.func.isRequired
};
export default class DepartmentBudgets extends Component {
constructor( props ) {
super(props);
}
render() {
const { budgets, updateBudget } = this.props;
const budgetsElements = budgets.map(( budget ) => {
return <Budget updateBudget={updateBudget} key={budget._id} budget={budget} />
});
return (
<Table>
<TableHeader adjustForCheckbox={false}
displaySelectAll={false}>
<TableRow onCellClick={this.handleCellClick}>
<TableHeaderColumn>Department</TableHeaderColumn>
<TableHeaderColumn>Budget</TableHeaderColumn>
<TableHeaderColumn>Owner</TableHeaderColumn>
</TableRow>
</TableHeader>
<TableBody stripedRows={false}>
{budgetsElements}
</TableBody>
</Table>
);
}
}
DepartmentBudgets.displayName = displayName;
DepartmentBudgets.propTypes = propTypes;
最后,预算部分负责提供实际预算。我还想包括在线编辑预算的功能,该功能包含在此组件中。但是,当我编辑预算时,组件不会重新渲染:
import React, { Component, PropTypes } from 'react';
import Table from '../../../../node_modules/material-ui/lib/table';
import numeral from 'numeral';
import InlineEdit from 'react-edit-inline';
const TableRow = Table.TableRow;
const TableRowColumn = Table.TableRowColumn;
const displayName = 'Budget';
const propTypes = {
budget : PropTypes.object.isRequired
};
export default class Budget extends Component {
constructor( props, context ) {
super(props, context);
console.log('Budget this:', this.props);
this.handleBudgetChange = this.handleBudgetChange.bind(this);
}
validateBudget( num ) {
return (Number(num) > 0 && Number(num) < 100 && !Number.isNaN(num));
}
handleBudgetChange( num ) {
const inputNum = Number(num.budget) > 1 ? Number(num.budget) / 100 : Number(num.budget);
const budgetId = this.props.budget._id;
this.props.updateBudget(budgetId, inputNum);
}
render() {
const cellStyle = {
textAlign : 'center'
};
const editCellStyle = {
cursor : 'pointer',
textDecoration : 'underline'
};
const { department, owner, budget } = this.props.budget;
const editControl = (
<InlineEdit
validate={this.validateBudget}
change={this.handleBudgetChange}
text={numeral(this.props.budget.budget).format('0.0%')}
paramName="budget"
activeClassName="editing"
/>
);
return (
<TableRow style={cellStyle}
displayBorder={false}>
<TableRowColumn>{department}</TableRowColumn>
<TableRowColumn style={editCellStyle}>{editControl}</TableRowColumn>
<TableRowColumn>{owner.name}</TableRowColumn>
<TableRowColumn style={editCellStyle}>Edit</TableRowColumn>
</TableRow>
);
}
}
Budget.displayName = displayName;
Budget.propTypes = propTypes;
当我在线编辑预算时,状态的值会发生变化,但组件不会重新渲染它。
我是否应该将<Budget />
组件连接到商店并在此处收听更改?
还是有更好的方法来解决我想要做的事情吗?
感谢您的帮助!
答案 0 :(得分:2)
快速浏览一下,是不是你没有将正确的道具传递给你的儿童组件?对于容器中的DepartmentBudgets,您是否应该将预算映射到预算&#39;而不是&#39; budgets.budgets&#39;?
答案 1 :(得分:0)
您确定this.props.updateBudget(budgetId, inputNum);
是否正确触发其父组件的功能?当它从容器传递下来时,你会想要做<DepartmentBudgets updateBudget={this.budgetDidchange.bind(this)} ... />
之类的事情。我不相信构造函数绑定弥补了这一点,但你总是可以在函数中抛出console.log("test")
来查看问题是否是函数本身而与Redux无关。
请参阅:https://facebook.github.io/react/tips/communicate-between-components.html