重用redux reducer和actions

时间:2016-09-12 10:47:43

标签: reactjs react-redux

假设我有一个节段缩减器来保存节的数据

const initialState = {
  data: [],
  section: ''
};

const sectionReducer = function(state = initialState, action) {
  switch(action.type) {
    case types.IMPORT_DATA_SUCCESS:
      return Object.assign(
        {},
        state,
        {
          section: action.section,
          data: action.data
        }
      );
  }
  return state;
}

我需要几个具有相同数据结构和操作的部分。那我怎么能这样做呢

import { combineReducers } from 'redux';
import sectionReducer from './sectionReducer';

const reducers = combineReducers({
  sectionA: sectionReducer,
  sectionB: sectionReducer
});

export default reducers;

行动就像

一样简单
import sectionAData from '../data/sectionAData';
...
export const importDataSuccess = (section, data) => {
  return {
    type: types.IMPORT_DATA_SUCCESS,
    section: section,
    data
  }
}

export const loadData = (section) => {
  const dataSet = (() => {
    switch(section) {
      case "SECTIONA":
        return sectionAData
        break;
      case "SECTIONB":
        return sectionBData
        break;
    }
  })()
  return (dispatch) => {
    dispatch(importDataSuccess(section, dataSet))
  }
}

上述方法的问题是我每次在this.props.dispatch(loadData("SECTIONA"))上调用componentA而在this.props.dispatch(loadData("SECTIONB"))调用componentB我在两个州树{{1}上获得sectionBData }和sectionA。即使首次调度sectionBsectionA已填充sectionB数据,即使尚未调度。

对这种情况重复使用减速器和动作的正确方法是什么?或者我是否必须为每个部分创建动作和减速器,即使它们是相同的?

=======更新=====

减速

sectionA

动作

const initialState = {
  data: []
};
const sectionReducer = function(state = initialState, action) {
  switch(action.type) {
    case types.IMPORT_DATA:
      if ( action.section ) {
        return state.data.push({ section: action.section, data: action.data });
      }
    break;
  }
  return state;
}
...
const reducers = combineReducers({
  sections: sectionReducer
});
export default reducers;

组件

export const importData= (section, data) => {
  return {
    type: types.IMPORT_DATA,
    section,
    data
  }
}
export const loadData = (section) => {
  const dataSet = (() => {
    switch(section) {
      case "SECTIONA":
        return sectionAData
        break;
      case "SECTIONB":
        return sectionBData
        break;
    }
  })()
  return (dispatch) => {
    dispatch(importData(section, dataSet))
  }
}

存储

class SectionWrapper extends Component {
  componentDidMount() {
    this.props.dispatch(loadData(this.props.const))
  }
  render() {
    return (
      <div>
        <Section
          title={this.props.title}
          id={this.props.id}
          data={this.props.data} />
      </div>
    )
  }
}
const mapStateToProps = function(store, ownProps) {
  const section = store.sections.find( (item) => { return item.section === ownProps.const; })
  const data = section.data
  return {
    data
  };
}
SectionWrapper.propTypes = {
  title: PropTypes.string.isRequired,
  id: PropTypes.string.isRequired,
  const: PropTypes.string.isRequired
}
export default connect(mapStateToProps)(SectionWrapper);

1 个答案:

答案 0 :(得分:1)

现在,当sectionReducer收到IMPORT_DATA_SUCCESS类型的操作时,它会将所有状态替换为收到的数据...因此状态中只能有一个部分和数据。显然是你不想要的。

您可以在sectionReducer

中执行的操作
const initialState = {
  data: [],
};

const sectionReducer = function(state = initialState, action) {

  switch(action.type) {
    case types.IMPORT_DATA_SUCCESS:
      // action contains { type, section, data }
      // added if statement to make sure data is not empty.
      if ( action.section && action.data ) {
        state.data.push({ section: action.section, data: action.data });
        return Object.assign( {}, state );
      }
      return state;

    case types.UPDATE_IMPORTED_DATA:
      // action contains { section, data }
      let index = state.data.findIndex( item => { return item.section === action.section; });
      state.data[index] = { section: action.section, data: action.data }
      return state;

    default:
     return state;

  }

}

使用此方法,您可以存储n个部分,并且可以非常轻松地更新它们。

当您想要访问特定部分的数据时,您可以

let findSectionByName = ( sections, section_name ) => {
  return sections.find( (item) => { return item.section === section_name; })
}
let section = findSectionByName( state.sections, 'SECTIONA' );

您还必须更改

const reducers = combineReducers({
  sectionA: sectionReducer,
  sectionB: sectionReducer
});

const reducers = combineReducers({
  sections: sectionReducer,
});