最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Design Redux actions and reducers for a React reusable component - Stack Overflow

programmeradmin2浏览0评论

I'm developing a large application with Redux and React and I decided to make some reusable components like custom checkboxes and radio buttons.

As I want to store this information into the Redux store to be able to debug state of the application easily and the same component have the same functionality everywhere, it seems a good idea to create reducers and actions for each component.

However Redux reducers return a new state and save it in the store with the name of the reducer as a key and this forbids having more than one component of the same type in the same page using the same actions and reducers but keeping different states.

I think there are two solutions to this problem:

  • Create different actions and reducers for each component that I use, even thought the component and it's functionalities are the same. This solutions doesn't seem a good solution because there will be a lot of redundant code.

  • Create actions with sufficient parameters to be able to differentiate each one in the reducer and that way change only the part of the state that is specified.

I went forward with the second option.

Actions file for the CheckBox component:

import {createAction} from 'redux-actions';

/****** Actions ******/
export const CHANGE_CHECKBOX_STATE = "CHANGE_CHECKBOX_STATE";

/****** Action creators ******/
export const changeCheckboxState = createAction(CHANGE_CHECKBOX_STATE, (block, name, state) => {
  return {
    block,
    name,
    state: {
      checked: state,
    }
  };
});

Reducers file for the CheckBox component:

import {handleActions} from 'redux-actions';

import {CHANGE_CHECKBOX_STATE} from './CheckBox.actions';

export const checkBoxComponent = handleActions({
  CHANGE_CHECKBOX_STATE: (state, action) => ({
    [action.payload.block]: {
      [action.payload.name]: action.payload.state
    }
  })
}, {});

I use block to specify the page, name to specify the name of the specific component (e.g. gender) and state as and object with the new state.

But this solution has some problems too:

  • Can't specify initial state of each component because the keys of the state are dynamic.
  • Complicates to much the store structure with a lot of nested states.
  • Aggregates data by component and not by form which will complicate debugging and it's logically incorrect.

I don't have enough experience with Redux and React to think of a better solution to this problem. But it seems to me that I'm missing something important about React-Redux relationship and this raises some questions:

  • Is it a good idea to store state of this reusable components into the Redux store?

  • Am I wrong in binding together React components with Redux actions and reducers?

I'm developing a large application with Redux and React and I decided to make some reusable components like custom checkboxes and radio buttons.

As I want to store this information into the Redux store to be able to debug state of the application easily and the same component have the same functionality everywhere, it seems a good idea to create reducers and actions for each component.

However Redux reducers return a new state and save it in the store with the name of the reducer as a key and this forbids having more than one component of the same type in the same page using the same actions and reducers but keeping different states.

I think there are two solutions to this problem:

  • Create different actions and reducers for each component that I use, even thought the component and it's functionalities are the same. This solutions doesn't seem a good solution because there will be a lot of redundant code.

  • Create actions with sufficient parameters to be able to differentiate each one in the reducer and that way change only the part of the state that is specified.

I went forward with the second option.

Actions file for the CheckBox component:

import {createAction} from 'redux-actions';

/****** Actions ******/
export const CHANGE_CHECKBOX_STATE = "CHANGE_CHECKBOX_STATE";

/****** Action creators ******/
export const changeCheckboxState = createAction(CHANGE_CHECKBOX_STATE, (block, name, state) => {
  return {
    block,
    name,
    state: {
      checked: state,
    }
  };
});

Reducers file for the CheckBox component:

import {handleActions} from 'redux-actions';

import {CHANGE_CHECKBOX_STATE} from './CheckBox.actions';

export const checkBoxComponent = handleActions({
  CHANGE_CHECKBOX_STATE: (state, action) => ({
    [action.payload.block]: {
      [action.payload.name]: action.payload.state
    }
  })
}, {});

I use block to specify the page, name to specify the name of the specific component (e.g. gender) and state as and object with the new state.

But this solution has some problems too:

  • Can't specify initial state of each component because the keys of the state are dynamic.
  • Complicates to much the store structure with a lot of nested states.
  • Aggregates data by component and not by form which will complicate debugging and it's logically incorrect.

I don't have enough experience with Redux and React to think of a better solution to this problem. But it seems to me that I'm missing something important about React-Redux relationship and this raises some questions:

  • Is it a good idea to store state of this reusable components into the Redux store?

  • Am I wrong in binding together React components with Redux actions and reducers?

Share Improve this question edited Aug 28, 2015 at 14:16 Roc asked Aug 28, 2015 at 14:01 RocRoc 2,7093 gold badges17 silver badges18 bronze badges 3
  • I don't understand why you'd need to store a control's state like this? Isn't backed by actual data? And that data doesn't give no craps about how it's rendered? Seems like bloat to me. – Chris Martin Commented Sep 7, 2015 at 10:54
  • @ChrisMartin I tried to explain here how I arrived to this decision, but I also said that I know i'm doing something wrong, I just don't see what it is. Can you explain to me how you would design it? Maybe that way I will see what's wrong with my approach. Thanks for responding! – Roc Commented Sep 8, 2015 at 14:58
  • Please, watch these videos: https://egghead.io/series/getting-started-with-redux... – Mike Commented Feb 4, 2016 at 18:16
Add a comment  | 

2 Answers 2

Reset to default 11

Don't describe your Redux reducers (your overall application state) in terms of the components that consume that state. Track it the other way, describing your application state in a descriptive manner and then have your "dumb" components consume that descriptive state.

Rather than tracking "The state of this checkbox for the form related to foo", track "this boolean value of foo" and then have the checkbox consume that state.

An example store for the checkbox:

const initialState = {
    someFooItem: { isCertainType: false }
};

export function foos(state = initialState, action) {
    switch(action.type){
        case(UPDATE_FOO_VALUE):
            return {
                ...state, 
                [action.payload.id]: {
                    isCertainType: action.payload.isCertainType
                }
            }
    }
}

An example checkbox consuming the store

class CheckBox extends React.Component {
    render() {
        return <input type="checkbox" checked={this.props.checked} />
    }
}

The parent component

class ParentComponent extends React.Component {
     render() {
         return <CheckBox checked={this.foo.isCertainType} />
     }
}

The fundamental mistake here is that you have 0 dumb components. Basic controls like checkboxes should be dumb components using just props, their parent having the responsibility to select and update the proper piece of state for a particular checkbox.

发布评论

评论列表(0)

  1. 暂无评论