首页 > 解决方案 > React-Redux 的 mapStateToProps 以意想不到的方式工作

问题描述

我有一个组件,它显示从 Redux 存储中获取的名称列表。该组件如下所示:

class Details extends React.Component {

  constructor (props) {
    super(props);
  }

  render () {
    const listName = [...this.props.listName];
    return (
      <div className="container detailsBox">
        <p>Details Grid:</p>
        {listName ? (
          listName.map((el, index) => {
            return (
              <li key={index}>
                {el}
              </li>
            )
          })
        ): null}
      </div>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    listName: state.listName
  }
}

export default connect(mapStateToProps)(Details);

listName注意这里我只从商店映射。但是即使登录控制台显示填充了数据,代码也不会显示<li>元素listNamelistName

但是当name也从商店中获取数据时,数据会按预期显示,修改mapStateToProps如下:

const mapStateToProps = (state) => {
  return {
    listName: state.listName,
    name: state.name
  }
}

我很困惑也很想知道为什么代码会以这种意想不到的方式运行?我在这里想念什么?

reducer 代码如下所示:

import { UPDATE_NAME, ADD_NAME } from '../actions/addName.action';

const initialState = {
  name: '',
  listName: new Set()
}

function rootReducer (state = initialState, action) {
  switch (action.type) {
    case ADD_NAME:
      return {
        name: '',
        listName: state.listName.add(action.payload)
      }
    case UPDATE_NAME:
      return {
        ...state,
        name: action.payload
      }
    default:
      return state;
  }
}

export default rootReducer;

和这样的动作:

export const ADD_NAME = 'ADD_NAME';
export const UPDATE_NAME = 'UPDATE_NAME';

export function addName (data) {
  return {
    type: ADD_NAME,
    payload: data
  }
}

export function updateName (name) {
  return {
    type: UPDATE_NAME,
    payload: name
  }
}

标签: reactjsreduxreact-redux

解决方案


这是因为你改变了状态。当你改变它时,listNames它仍然指向内存中的同一个对象,并且反应认为什么都没有改变,而内容listNames却改变了。您应该返回一个新对象。

case ADD_NAME:
  return {
    name: '',
    listName: new Set([...state.listName, action.payload]),
  }

但不建议Set在reducers中使用s。相反,您可以将您的存储listNames为数组并使用 lodashunion函数仅具有唯一值。

import { union } from 'lodash';

const initialState = {
  name: '',
  listName: []
}

// some code

case ADD_NAME:
  return {
    name: '',
    listName: union(state.listNames, action.payload)
  }

推荐阅读