【问题标题】:<Redux> state updated but nor re-render<Redux> 状态已更新但未重新渲染
【发布时间】:2018-06-10 18:03:22
【问题描述】:

我刚开始学习 React Native + Redux。看来我成功更新了状态,但视图没有改变(没有重新渲染)。谁能给我一个建议来解决这个问题...?

我尝试使用 console.log 进行调试并点击屏幕。

"selectedMenuMap": 对象 { “项目 2”:是的, “项目3”:假, "}, 这只是日志的一部分,我可以看到状态实际上发生了变化......

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;

容器.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

【问题讨论】:

  • 能否也添加 MenuList 组件的代码? redux 代码似乎是正确的
  • @dentemm 感谢您的帮助!做到了!

标签: javascript reactjs react-native redux


【解决方案1】:

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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-23
    相关资源
    最近更新 更多