2015-11-13 22 views
5

私はまだ反応しています。あるページには、1トンのテキスト入力があります。以下のように見える私の減速でreact/reduxでのアクションとレデューサーの共有

export function setInputName(string) { 
    return { 
    type: 'SET_CURRENT_NAME', 
    payload: {value: string} 
    }; 
} 
export function setInputCity(string) { 
    return { 
    type: 'SET_CURRENT_CITY', 
    payload: {value: string} 
    }; 
} 

:しばらくして私は私のアクションファイルが同じことをやった機能を持っていますが、異なる入力のために気づき始め

export function currentName(state='', {type, payload}) { 
    switch (type) { 
    case 'SET_CURRENT_NAME': 
    return payload.value; 
    default: 
    return state; 
    } 
} 
export function currentCity(state='', {type, payload}) { 
    switch (type) { 
    case 'SET_CURRENT_CITY': 
    return payload.value; 
    default: 
    return state; 
    } 
} 

そして、私のコンポーネントは、これらの複数の入力ました:

import {Component, PropTypes} from 'react'; 
import {connect} from 'react-redux'; 
import {bindActionCreators} from 'redux'; 
import {setInputName, setInputCity} from 'actions/form'; 

export default class Form extends Component { 
    static propTypes = { 
    setInputName: PropTypes.func.isRequired, 
    setInputCity: PropTypes.func.isRequired, 
    currentName: PropTypes.string.isRequired, 
    currentCity: PropTypes.string.isRequired 
    } 
    render() { 
    let {setInputName, setInputCity, currentName, currentCity} = this.props; 
    return (
     <div> 
     <input 
      type="text" 
      placeholder="Name" 
      onChange={(e) => setInputName(e.currentTarget.value)} 
      value={currentName} 
     /> 
     <input 
      type="text" 
      placeholder="City" 
      onChange={(e) => setInputCity(e.currentTarget.value)} 
      value={currentCity} 
     /> 
     </div> 
    ); 
    } 
} 

function select(state) { 
    return { 
    currentName: state.form.currentName, 
    currentCity: state.form.currentCity 
    }; 
} 

function actions(dispatch) { 
    return bindActionCreators({ 
    setInputName: setInputName, 
    setInputCity: setInputCity, 
    }, dispatch); 
} 

export default connect(select, actions)(Form); 

非常にドライではないとすぐに私は間違って何かをしていたと思った。アプリケーションのすべてのページとコンポーネントのすべてのテキスト入力に対して共通のsetInputValueアクションを設定する良い方法はありますか?私はまた、すべての入力に共通の減速器を使用したいと考えています。ありがとうございました。

UPDATE

はここで働く私の総一例ですが、これはまだ少し複雑で、より良い方法がなければならないような気がします。基本的にはレデューサーで、その入力が使用され、状態にまだ追加されているかどうかを確認します。そうでない場合は追加します。もしそうなら、私はその価値を更新するだけです。 EDIT私はこれが実際にはうまくいかないと嘘をついた。要求されるように、ここで[OK]を

// actions 
export function updateTextInput(name, value) { 
    return { 
    type: 'SET_CURRENT_TEXT_INPUT', 
    payload: {name: name, value: value} 
    }; 
} 

// reducer 
export function currentTextInput(state=[], {type, payload}) { 
    switch (type) { 
    case 'SET_CURRENT_TEXT_INPUT': 
    let newState = state; 
    let curInput = state.findIndex(function(elem) { 
     return elem.name === payload.name; 
    }); 
    if (curInput === -1) { 
     newState.push({name: payload.name, value: payload.value}); 
    } else { 
     newState[curInput].value = payload.value; 
    } 
    return newState; 
    default: 
    return state; 
    } 
} 

// component 
... 
render() { 
    let {updateTextInput, currentTextInput} = this.props; 
    return (
    <div> 
     <input 
     type="text" 
     placeholder="Name" 
     onChange={(e) => updateTextInput('name', e.currentTarget.value)} 
     value={currentTextInput.name} 
     /> 
     <input 
     type="text" 
     placeholder="City" 
     onChange={(e) => updateTextInput('city', e.currentTarget.value)} 
     value={currentTextInput.city} 
     /> 
    </div> 
); 
} 
... 

答えて

5

は一例です。それは次のようになります、のは、私はユーザーデータモデルを持っているとしましょう:

{ 
    id: 1, 
    name: 'Some Name', 
    email: '[email protected]', 
    age: 21 
} 

を彼らは方法あなたが現在あなたがSET_USER_NAME、SET_USER_EMAIL、SET_USER_AGEアクションを持っている必要があるだろうセットアップ、それを持っています。更新された値のオブジェクトを引数として受け取るUPDATE_USERアクションを持つことができるときは、それらのすべての必要はありません。

はあなたが

のようなユーザーの状態(ユーザーの配列)を更新したい減速機のユーザーが

updateUser(1, { name: 'New Name' })

ようUPDATE_USERアクションを呼ぶだろう最初のユーザーのために新しい名前を設定するには

function updateUser(usersState, id, attrs) { 
    return usersState.map(user => 
    user.id === id ? 
    Object.assign({}, user, attrs) : 
    user 
); 
} 
+0

これはかなりのことを明確にしています。 1つのページに無関係なフォームが複数あり、特定のモデルが1つもない場合はどうなりますか?何らかの形で共通のアクション/レデューサーを使用することはできますか?ページ全体に1つのgiaormousモデルを持たずに。 –

+3

各モデルには、独自のスライスを受け取る独自のレデューサーが必要です。あなたは正しいかもしれませんが、さまざまなレデューサーでインポートして使用できる単一の更新機能 – slightlytyler

6

コードを簡素化するための小さな第一歩は、高次の縮小/機能を使用することです。私は最近、このような行動を思い付いた

function makePropReducer(actionType, prop) { 
    return (state = '', {type, payload}) => { 
    if (type === actionType) { 
     return payload[prop]; 
    } 
    return state; 
    }; 
} 

export const currentName = makePropReducer('SET_CURRENT_NAME', 'value'); 
export const currentCity = makePropReducer('SET_CURRENT_CITY', 'value'); 
+0

これは素晴らしいです。間違いなくこれを使用します。ありがとうございました –

1

export function controlStateChange(controlName, propertyName, value) { 
    return { type: 'CONTROL_STATE_CHANGE', payload: { controlName, propertyName, value } }; 
} 

そしてcorrespoding減速、

const actionHandlers = { 
    'CONTROL_STATE_CHANGE': (state, payload) => { 
    const controls = { 
     [payload.controlName]: { 
     [payload.propertyName]: payload.value 
     } 
    }; 

    return {...state, controls }; 
    } 
}; 

それはかなり一般的であり、私はあなたがあまりにも必要に役立つことを願っています。

0

状態への入力を保存するためには、使用することができますredux-form

それはあなたの質問は本当に共有減速/アクションに関連していないようです。 アクション/レデューサーを共有するために、1つ書きました。あなたは一見を持つことができます。redux-conditional

関連する問題