reuse redux reducers and actions



假设我有一个section reducer来保存section的数据

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))
  }
}

上述方法的问题是每次我调用componentA上的this.props.dispatch(loadData("SECTIONA"))componentB上的this.props.dispatch(loadData("SECTIONB"))时,我在状态树sectionAsectionB上都得到sectionBData。即使sectionA第一次被调度,sectionB已经被sectionA数据填充,即使它还没有被调度。

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

======= UPDATE =====

齿轮

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);

存储
const createStoreWithMiddleware  = compose(
  applyMiddleware(
    thunkMiddleware,
    createLogger()
  ),
  window.devToolsExtension ? window.devToolsExtension() : f => f
)
const store = createStore(
  reducers,
  createStoreWithMiddleware
);
export default store;

现在,当sectionReducer接收到类型为IMPORT_DATA_SUCCESS的动作时,它将整个状态替换为接收到的数据…所以状态中可能只有一个section和数据。,这显然是你不想要的。

你可以做的是,在你的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,
});

相关内容

  • 没有找到相关文章

最新更新