redux 状态已更改但连接的组件未更新,无法理解突变
redux state changed but connected component didn't update, can't understand mutation
我知道问题是有突变。因为大多数情况下不会因此而重新渲染。但是,无法理解我这样做的方式有什么问题。
对于我从后端获取的数据,一切都很好,但如果我尝试从 FE 更改状态,它就无法正常工作。
问题在于 groupDevicesBySelectedFilter(devicesGroups)。
操作完成后,我得到的响应是控制台中的状态已更改,但如标题所示,FE 上没有任何更改。
Filter.tsx
import * as React from 'react'
import {IAppState} from '../../reducers'
import {connect} from 'react-redux'
import { Dropdown, Header, Icon } from 'semantic-ui-react'
import { INodeTreeFilters, INodeTreeDevicesInfo } from './type-definition';
import * as nodeTreeActions from '../../actions/node-tree';
import * as _ from 'lodash';
interface INodeTreeFilterProps{
filters: INodeTreeFilters;
selectGroupsFilter: any;
groupDevicesBySelectedFilter: typeof nodeTreeActions.groupDevicesBySelectedFilter;
devices: INodeTreeDevicesInfo
}
class NodeTreeFilter extends React.Component<INodeTreeFilterProps>{
public render() {
const {filters, selectGroupsFilter, groupDevicesBySelectedFilter, devices} = this.props;
const groupsFilterSelected = (event: React.SyntheticEvent<HTMLDivElement>, data: any) => {
selectGroupsFilter({id:data.value});
const devicesGroups=_.chain(devices).groupBy(data.value).map((v, i) => {
return {
id: i,
name: i,
devices: v
}
}).value();
groupDevicesBySelectedFilter(devicesGroups);
}
return (
<Header as='h4'>
<Icon name='filter' />
<Header.Content>
Group nodes by {' '}
<Dropdown
inline = {true}
options={filters}
onChange={groupsFilterSelected}
/>
</Header.Content>
</Header>
)
}
}
const mapStateToProps = (state: IAppState) => (
{
filters: state.sidebar.filters,
devices: state.sidebar.devices,
});
const mapDispatchToProps = {
selectGroupsFilter: nodeTreeActions.selectNodeTreeGroupFilter,
groupDevicesBySelectedFilter: nodeTreeActions.groupDevicesBySelectedFilter
};
export default connect(mapStateToProps, mapDispatchToProps)(NodeTreeFilter)
我的减速器
export const devicesGroupsReducer = (state: IDevicesGroups = [], action: IActionWithPayload) => {
switch (action.type) {
case nodeTreeActions.GROUP_DEVICES_BY_SELECTED_FILTER:
return action.payload
default:
return state;
} };
export interface IActionWithPayload extends Action {
payload: any;
}
最后 我的child组件,应该重新渲染。
import * as React from 'react'
import {List} from 'semantic-ui-react'
import {IAppState,} from '../../reducers'
import {connect} from 'react-redux'
import {INodeTreeDevicesInfo, INodeTreeDeviceInterfaces, IDevicesGroups} from './type-definition'
import * as nodeTreeActions from '../../actions/node-tree'
// import * as nodeTreeService from '../../services/node-tree'
import {requestError} from "../../actions/error";
interface INodeTreeProps{
devices: INodeTreeDevicesInfo ;
interfaces: INodeTreeDeviceInterfaces;
getDeviceInterfaces: typeof nodeTreeActions.getNodeTreeDeviceInterfaces;
requestError: typeof requestError;
deviceGroups: IDevicesGroups;
}
class NodeTree extends React.Component<INodeTreeProps> {
public generateParentTree = (array: any) => {
const tree = array.map((item:any) => (
<List.Item key={item.id}>
<List.Icon name={ "caret right"} />
<List.Content onClick={this.generateChildren} verticalAlign='middle'>
<List.Description>{item.name}</List.Description>
</List.Content>
</List.Item>
))
return tree
}
public generateChildren = () => {
console.log('I will generate children')
}
public render() {
const {devices, deviceGroups} = this.props;
const parentArray = deviceGroups !== undefined && deviceGroups.length !== 0 ? deviceGroups : devices;
const Tree = this.generateParentTree(parentArray)
console.log('')
return (
<div>
<List>
{Tree}
</List>
</div>
);
}
}
const mapStateToProps = (state: IAppState) => (
{
devices: state.sidebar.devices,
interfaces: state.sidebar.interfaces,
deviceGroups: state.sidebar.deviceGroups
});
const mapDispatchToProps = {
requestError,
getDeviceInterfaces: nodeTreeActions.getNodeTreeDeviceInterfaces
};
export default connect(mapStateToProps, mapDispatchToProps)(NodeTree)
请不要介意 public 和代码中的私有状态
您正在改变减速器中的状态。您需要 return 一个新的状态对象并使用您的负载更新它。
return {
...state,
IDevicesGroups: [...state.IDevicesGroups, action.payload]
}
应该是这样的。
我知道问题是有突变。因为大多数情况下不会因此而重新渲染。但是,无法理解我这样做的方式有什么问题。
对于我从后端获取的数据,一切都很好,但如果我尝试从 FE 更改状态,它就无法正常工作。 问题在于 groupDevicesBySelectedFilter(devicesGroups)。 操作完成后,我得到的响应是控制台中的状态已更改,但如标题所示,FE 上没有任何更改。
Filter.tsx
import * as React from 'react'
import {IAppState} from '../../reducers'
import {connect} from 'react-redux'
import { Dropdown, Header, Icon } from 'semantic-ui-react'
import { INodeTreeFilters, INodeTreeDevicesInfo } from './type-definition';
import * as nodeTreeActions from '../../actions/node-tree';
import * as _ from 'lodash';
interface INodeTreeFilterProps{
filters: INodeTreeFilters;
selectGroupsFilter: any;
groupDevicesBySelectedFilter: typeof nodeTreeActions.groupDevicesBySelectedFilter;
devices: INodeTreeDevicesInfo
}
class NodeTreeFilter extends React.Component<INodeTreeFilterProps>{
public render() {
const {filters, selectGroupsFilter, groupDevicesBySelectedFilter, devices} = this.props;
const groupsFilterSelected = (event: React.SyntheticEvent<HTMLDivElement>, data: any) => {
selectGroupsFilter({id:data.value});
const devicesGroups=_.chain(devices).groupBy(data.value).map((v, i) => {
return {
id: i,
name: i,
devices: v
}
}).value();
groupDevicesBySelectedFilter(devicesGroups);
}
return (
<Header as='h4'>
<Icon name='filter' />
<Header.Content>
Group nodes by {' '}
<Dropdown
inline = {true}
options={filters}
onChange={groupsFilterSelected}
/>
</Header.Content>
</Header>
)
}
}
const mapStateToProps = (state: IAppState) => (
{
filters: state.sidebar.filters,
devices: state.sidebar.devices,
});
const mapDispatchToProps = {
selectGroupsFilter: nodeTreeActions.selectNodeTreeGroupFilter,
groupDevicesBySelectedFilter: nodeTreeActions.groupDevicesBySelectedFilter
};
export default connect(mapStateToProps, mapDispatchToProps)(NodeTreeFilter)
我的减速器
export const devicesGroupsReducer = (state: IDevicesGroups = [], action: IActionWithPayload) => {
switch (action.type) {
case nodeTreeActions.GROUP_DEVICES_BY_SELECTED_FILTER:
return action.payload
default:
return state;
} };
export interface IActionWithPayload extends Action {
payload: any;
}
最后 我的child组件,应该重新渲染。
import * as React from 'react'
import {List} from 'semantic-ui-react'
import {IAppState,} from '../../reducers'
import {connect} from 'react-redux'
import {INodeTreeDevicesInfo, INodeTreeDeviceInterfaces, IDevicesGroups} from './type-definition'
import * as nodeTreeActions from '../../actions/node-tree'
// import * as nodeTreeService from '../../services/node-tree'
import {requestError} from "../../actions/error";
interface INodeTreeProps{
devices: INodeTreeDevicesInfo ;
interfaces: INodeTreeDeviceInterfaces;
getDeviceInterfaces: typeof nodeTreeActions.getNodeTreeDeviceInterfaces;
requestError: typeof requestError;
deviceGroups: IDevicesGroups;
}
class NodeTree extends React.Component<INodeTreeProps> {
public generateParentTree = (array: any) => {
const tree = array.map((item:any) => (
<List.Item key={item.id}>
<List.Icon name={ "caret right"} />
<List.Content onClick={this.generateChildren} verticalAlign='middle'>
<List.Description>{item.name}</List.Description>
</List.Content>
</List.Item>
))
return tree
}
public generateChildren = () => {
console.log('I will generate children')
}
public render() {
const {devices, deviceGroups} = this.props;
const parentArray = deviceGroups !== undefined && deviceGroups.length !== 0 ? deviceGroups : devices;
const Tree = this.generateParentTree(parentArray)
console.log('')
return (
<div>
<List>
{Tree}
</List>
</div>
);
}
}
const mapStateToProps = (state: IAppState) => (
{
devices: state.sidebar.devices,
interfaces: state.sidebar.interfaces,
deviceGroups: state.sidebar.deviceGroups
});
const mapDispatchToProps = {
requestError,
getDeviceInterfaces: nodeTreeActions.getNodeTreeDeviceInterfaces
};
export default connect(mapStateToProps, mapDispatchToProps)(NodeTree)
请不要介意 public 和代码中的私有状态
您正在改变减速器中的状态。您需要 return 一个新的状态对象并使用您的负载更新它。
return {
...state,
IDevicesGroups: [...state.IDevicesGroups, action.payload]
}
应该是这样的。