简体   繁体   中英

Passing multiple props and actions in react / redux

I'm using React and Redux in my web app.
In the login page, I have multiple fields (inputs).
The login page in composed from multiple components to pass the props to.

I was wondering how should I pass the props and update actions.
For example, lets assume I have 5 inputs in my login page.

LoginPage (container) -> AuthenticationForm (Component) -> SignupForm (Component)

In the LoginPage I map the state and dispatch to props,
and I see 2 options here:

mapStateToProps = (state) => ({
  input1: state.input1,
  ...
  input5: state.input5
})

mapDispatchToProps = (dispatch) => ({
  changeInput1: (ev) => dispatch(updateInput1(ev.target.value))
  ...
  changeInput5: (ev) => dispatch(updateInput5(ev.target.value))
})

In this solution, I need to pass a lot of props down the path (the dispatch actions and the state data).

Another way to do it is like this:

mapStateToProps = (state) => ({
  values: {input1: state.input1, ..., input5: state.input5}
})

mapDispatchToProps = (dispatch) => ({
  update: (name) => (ev) => dispatch(update(name, ev.target.value))
})

In this solution, I have to keep track and send the input name I want to update.

How should I engage this problem?
It seems like fundamental question, since a lot of forms have to handle it,
but I couldn't decide yet what would suit me now and for the long run.

What are the best practices?

I think best practice would be to handle all of this logic in the React component itself. You can use component's state to store input's data and use class methods to handle it. There is good explanation in React docs https://reactjs.org/docs/forms.html

You probably should pass data in Redux on submit. Ether storing whole state of the form as an object, or not store at all and just dispatching action with api call.

TL;DR. it's a more 'general' coding practice. But let's put it under a react-redux context.

Say if you go with your first approach, then you will probably have 5 actionCreators as:

function updateInput1({value}) {  return {type: 'UPDATE_INPUT1', payload: {value}} }
...
function updateInput5({value}) {  return {type: 'UPDATE_INPUT5', payload: {value}} }

Also if you have actionTypes, then:

const UPDATE_INPUT1 = 'UPDATE_INPUT1'
...
const UPDATE_INPUT5 = 'UPDATE_INPUT5'

The reducer will probably look like:

function handleInputUpdate(state = {}, {type, payload: {value}}) {
  switch (type) {
    case UPDATE_INPUT1: return {..., input1: value}
    ...
    case UPDATE_INPUT5: return {..., input5: value}
    default: return state
  }
}

What's the problem? I don't think you're spreading too many props in mapStateToProps / mapDispatchToProps , Don't repeat yourself !

So naturally, you want a more generic function to avoid that:

const UPDATE_INPUT = 'UPDATE_INPUT'

function updateInput({name, value}) { return {type: UPDATE_INPUT, payload: {name, value}} }

function handleInputUpdate(state = {inputs: null}, {type, payload: {name, value}}) {
  switch (type) {
    case UPDATE_INPUT: return {inputs: {...state.inputs, [name]: value}}
    default: return state
  }
}

Finally, the "selector" part, based upon how the state was designed, get component's props from it would be fairly trivial:

function mapStateToProps(state) { return {inputs: state.inputs} }
function mapDispatchToProps(dispatch) { return {update(name, value) { dispatch(updateInput(name, value)) } }

In summary, it's not necessarily a redux/react problem, it's more how you design app state, redux just offers you utilities and poses some constraints to enable "time traveling" (state transitions are made explicit within a mutation handler based on a separate action).

Best practice to handle this problem is having a local state on your Form Component and managing it locally because I believe it's not a shared state. onSubmit you could dispatch your action passing down the state to the action which is required in making an API call or posting it to your server.

If you try to keep updating your store as the user types, it will keep dispatching the action which might cause problems in future. You read more here Handling multiple form inputs in react

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM