<redux>状态更新但不重新渲染

时间:2018-06-10 08:10:23

标签: javascript reactjs react-native redux

我刚开始学习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

1 个答案:

答案 0 :(得分:3)

Object.assign()仅执行浅拷贝。所以这句话并不像你期望的那样有用。

  let newState = Object.assign({}, state);

虽然newStatestate是不同的对象,但嵌套的newState.selectedMenuMap指向与state.selectedMenuMap相同的对象。你不能在不改变两者的情况下改变一个。

相反,请确保不要修改原始状态。这样的事情应该有效。

const newState = { ...state,
  selectedMenuMap: { ...state.selectedMenuMap,
    [action.key]: !state.selectedMenuMap[action.key]
  }
}

每个展开操作{...foo}都与Object.assign({}, foo)相同,因此我们创建了statestate.selectedMenuMap的浅表副本。现在state.selectedMenuMapnewState.selectedMenuMap指向不同的对象,而redux将知道连接到状态树的这一部分的组件应该被重新渲染。

这看起来有点复杂,原始状态是否发生变化可能并不明显。

更新嵌套状态切片时避免改变现有状态的一种方法是使用诸如Ramda.js之类的库,它永远不会改变作为参数传入的对象。

const newState = R.over(R.lensPath(['selectedMenuMap', action.key]), R.not, state)