I am still reacting very strongly / reducing noob. On one page I have a ton of text inputs. After a while, I began to notice that my action file has functions that perform the same thing, but for different inputs:
export function setInputName(string) { return { type: 'SET_CURRENT_NAME', payload: {value: string} }; } export function setInputCity(string) { return { type: 'SET_CURRENT_CITY', payload: {value: string} }; }
With my gearbox it looks like:
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; } }
And my component had these multiple inputs:
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);
This is not very DRY, and I immediately thought that I was doing something wrong. Is there a good way to have a common setInputValue action for all text inputs on every page and component of my application? I would also like to use a common gearbox for each input. Thanks.
UPDATE
Here is my rude example that works, but I feel this is still a bit confusing and there should be a better way. Basically in the gearbox I check if this input has been used and added to the state yet. If not, add it. If so, I just update its value. EDIT I lied that this really didn't work.
// 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> ); } ...