我刚开始学习React Native + Redux。我似乎成功更新了状态,但视图没有改变(没有重新渲染)。谁能给我一个解决这个问题的建议......?
我尝试使用console.log进行调试,然后点击屏幕。
“selectedMenuMap”:Object { “item2”:是的, “item3”:false, “}, 这只是日志的一部分,我可以看到状态实际上已经改变了......
Reducer.js
import { SELECT_MENU } from './actions.js';
const initialState = {
menu:
[
{key: 'item1', title: 'AAA',
detail: [
{key: 'detail_item1', title: 'AA', price: '1000', time: '30'},
{key: 'detail_item2', title: 'AB', price: '1100', time: '35'},
{key: 'detail_item3', title: 'AC', price: '1200', time: '40'},
]},
{key: 'item2', title: 'BBB',
detail: [
{key: 'detail_item1', title: 'BA', price: '1000', time: '30'},
{key: 'detail_item2', title: 'BB', price: '1100', time: '35'},
{key: 'detail_item3', title: 'BC', price: '1200', time: '40'},
]},
{key: 'item3', title: 'CCC',
detail: [
{key: 'detail_item1', title: 'CA', price: '1000', time: '30'},
{key: 'detail_item2', title: 'CB', price: '1100', time: '35'},
{key: 'detail_item3', title: 'CC', price: '1200', time: '40'},
]},
],
selectedMenuMap: {}
};
function menuList(state = initialState, action) {
switch (action.type) {
case SELECT_MENU:
console.log('state');
let newState = Object.assign({}, state);
newState.selectedMenuMap[action.key] = !state.selectedMenuMap[action.key];
console.log(newState === state);
return newState;
default:
return state;
}
}
export default menuList;
Container.js
import MenuList from '../components/MenuList.js';
import { selectMenu } from '../actions.js';
import { connect } from 'react-redux';
const mapStateToProps = state => ({
menu: state.menu,
selectedMenuMap: state.selectedMenuMap,
});
const mapDispatchToProps = dispatch => {
return {
onPressMenu: key => {
dispatch(selectMenu(key))
},
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(MenuList);
components.js
import React, { Component, Purecomponent } from 'react';
import {
FlatList,
} from 'react-native';
import MenuItem from './MenuItem.js';
export default class MenuList extends React.PureComponent {
_renderItem = ({item}) => (
<MenuItem
id={item.key}
onPressItem={() => this.props.onPressMenu(item.key)}
selected={this.props.selectedMenuMap[item.key]}
title={item.title}
detail={item.detail}
/>
);
render() {console.log(this.props);
return (
<FlatList
data={this.props.menu}
renderItem={this._renderItem}
/>
);
}
}
这是一个问题吗?state和newState是一样的吗?
function menuList(state = initialState, action) {
switch (action.type) {
case SELECT_MENU:
console.log('reducer');
let newState = Object.assign({}, state);
newState.selectedMenuMap[action.key] = !state.selectedMenuMap[action.key];
console.log('oldState');
console.log(state.selectedMenuMap);
console.log('newState');
console.log(newState.selectedMenuMap);
console.log(newState.selectedMenuMap === state.selectedMenuMap);
return newState;
default:
return state;
}
}
17:35:33: reducer
17:35:33: oldState
17:35:33: Object {
17:35:33: "item3": true,
17:35:33: }
17:35:33: newState
17:35:33: Object {
17:35:33: "item3": true,
17:35:33: }
17:35:33: true
答案 0 :(得分:3)
Object.assign()
仅执行浅拷贝。所以这句话并不像你期望的那样有用。
let newState = Object.assign({}, state);
虽然newState
和state
是不同的对象,但嵌套的newState.selectedMenuMap
指向与state.selectedMenuMap
相同的对象。你不能在不改变两者的情况下改变一个。
相反,请确保不要修改原始状态。这样的事情应该有效。
const newState = { ...state,
selectedMenuMap: { ...state.selectedMenuMap,
[action.key]: !state.selectedMenuMap[action.key]
}
}
每个展开操作{...foo}
都与Object.assign({}, foo)
相同,因此我们创建了state
和state.selectedMenuMap
的浅表副本。现在state.selectedMenuMap
和newState.selectedMenuMap
指向不同的对象,而redux将知道连接到状态树的这一部分的组件应该被重新渲染。
这看起来有点复杂,原始状态是否发生变化可能并不明显。
更新嵌套状态切片时避免改变现有状态的一种方法是使用诸如Ramda.js之类的库,它永远不会改变作为参数传入的对象。
const newState = R.over(R.lensPath(['selectedMenuMap', action.key]), R.not, state)