2015-08-28 53 views
19

我正在開發一個使用Redux和React的大型應用程序,並決定製作一些可重用的組件,如自定義複選框和單選按鈕。設計Reux可重用組件的動作和縮減器

因爲我想將這些信息存儲在Redux存儲中,以便能夠輕鬆地調試應用程序的狀態,並且同一組件在任何地方都具有相同的功能,爲每個組件創建減速器和操作似乎是個不錯的主意。

但是,Redux reducer返回一個新的狀態並將其以reducer的名稱作爲關鍵字保存在存儲中,並且禁止在同一頁面中使用相同的動作和reducer而保留相同類型的多個組件不同的州。

我認爲有兩個解決此問題:

  • 創建,我使用的每個組件不同的操作和減速器,甚至認爲該組件,它的功能是相同的。這個解決方案似乎不是一個好的解決方案,因爲會有很多冗餘的代碼。

  • 創建具有足夠參數的操作,以便能夠區分reducer中的每個參數,並且只更改指定的狀態部分。

我繼續第二個選項。

操作文件中爲CheckBox組件:

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

減速立案CheckBox組件:

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 
    } 
    }) 
}, {}); 

我用block指定的頁面,name指定特定組件的名稱(例如性別),並以新狀態作爲對象。

但這種方法也存在一些問題:

  • 不能指定每個組件的初始狀態,因爲狀態的鍵是動態的。
  • 使很多嵌套狀態的商店結構複雜化。
  • 按組件聚集數據而不按形式聚合,這會使調試複雜化,並且在邏輯上不正確。

我沒有足夠的Redux和React經驗來想出更好的解決方案來解決這個問題。但在我看來,我失去了大約陣營,Redux的關係,一些重要的東西,這提出了一些問題:

  • 這是個好主意來存儲這些可重用的組件的狀態進入終極版商店嗎?

  • 我錯誤的將React組件與Redux動作和縮減器綁定在一起嗎?

+0

我不明白爲什麼你需要存儲控件的狀態是這樣的?是不是由實際數據支持?這些數據並沒有給出它如何呈現的胡扯嗎? 看起來像膨脹對我。 –

+0

@ChrisMartin我在這裏試圖解釋我是如何到達這個決定的,但我也說過,我知道我做錯了什麼,我只是看不到它是什麼。你能向我解釋你將如何設計它?也許這樣我會看到我的方法有什麼問題。感謝您的迴應! – Roc

+0

請觀看以下視頻:[https://egghead.io/series/getting-started-with-redux](https://egghead.io/series/getting-started-with-redux)... – Mike

回答

4

這裏最根本的錯誤是你有0個啞組件。像複選框這樣的基本控件應該是僅使用道具的啞組件,他們的父母有責任選擇和更新特定複選框的適當狀態。

+0

Nono ,它們都是愚蠢的組件,動作和縮減器僅供父組件和商店使用。 – Roc

8

不要根據使用該狀態的組件描述Redux Reducer(您的整體應用程序狀態)。用另一種方式跟蹤它,以描述性的方式描述你的應用程序狀態,然後讓你的「愚蠢的」組件消耗描述性狀態。

而不是跟蹤「與foo相關的表單的此複選框的狀態」,跟蹤「此foo的布爾值」,然後讓複選框消耗該狀態。

一個例子商店的複選框:

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

一個例子複選框消耗店

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

父組件

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

如果我正確理解你,你的解決方案完全不能解決我的問題,因爲你概括了複選框的形式,但是如果我有三個複選框,每個複選框都有不同的興趣(例如體育,冒險,烹飪)其中我需要創建一個不同的減速器,甚至認爲功能是一樣的。 – Roc

+1

運動,冒險,烹飪將是「興趣」,所以你可以有一個像'{興趣:{烹飪:真實的,運動:假的,冒險:假的}}'的減速器,並用它來表示視圖。 – Danita