在Redux中更新对象的状态

时间:2020-06-10 15:02:21

标签: reactjs redux react-redux

使用一个函数输入多个输入来更新Redux中的对象状态的最佳方法是什么?

我有3个输入-如果可能的话,我想使用一个函数或最佳实践将对应的输入字段更新为redux对象字段。

// Contact.js

this.state = {
    contactInfo: {
        firstName: '',
        address: '',
        city: '',
    }
}


onChangeInfo = (event, action) => {
    const { dispatch } = this.props;
    const { contactInfo } = this.state;

    // Is this an issue?
    contactInfo[event.target.name] = event.target.value;

    if (action === 'CHANGE') {
        dispatch(updateContactInfo(contactInfo));
        this.setState({ contactInfo });
    } else {
        this.setState({ contactInfo });
    }
}

render() {

const { firstName, address, city } = this.state.contactInfo;

return (
<div>
    <div>
        <input placeholder=" " type="text" name='firstName' value={firstName} onChange={(e) => this.onChangeInfo(e, 'CHANGE')} required id="" />
        <div className="placeholder"><span>First &amp; last name</span></div>
    </div>
    <div>
        <input placeholder=" " type="text" name="address" value={address} onChange={(e) => this.onChangeInfo(e, 'CHANGE')} required id="" />
        <div className="placeholder"><span>Address</span></div>
    </div>
    <div>
        <input placeholder=" " type="text" name="city" value={city} onChange={(e) => this.onChangeInfo(e, 'CHANGE')} required id="" />
        <div className="placeholder"><span>City</span></div>
    </div>
</div>
)}

//减速器


const initialState = {
    contactInformation: [],
}

export default function (state, action) {
    state = state === undefined ? initialState : state;
    switch (action.type) {
        case 'CONTACT_INFO': {
            state.contactInformation.test.info = payload;
            return Object.assign({}, state, action.payload);
        }
        default: return state;
    }
}

3 个答案:

答案 0 :(得分:1)

我建议您保持三种不同的操作作为最佳实践 因为动作始终是纯函数,并且特定于一个特定操作。

export const firstName = (firstName) => ({
    type : 'FIRST_NAME',
    payload : firstName
});

export const address = (address) => ({
    type : 'ADDRESS',
    payload : address
});

export const city = (city) => ({
    type : 'CITY',
    payload : city
});

然后,在减速器中,根据action.type更新商店。

答案 1 :(得分:1)

我看不到using setState in this case的重点

this.state = {
    contactInfo: {...this.props}
}

onChangeInfo = ({target: {name, value}}, action) => {
    const { dispatch } = this.props;
    const contactInfo = {[name]: value};

    if (action === 'CHANGE') {
        dispatch(updateContactInfo(contactInfo));
    }
}

示例

const { Component, useState, useEffect } = React;
const { bindActionCreators, combineReducers, createStore, applyMiddleware, compose } = Redux;
const { connect, Provider } = ReactRedux;

const initalState = {
    contactInfo: {
      firstName: '',
      address: '',
      city: ''
  }
}

const reducer = (state = initalState, action) => {
  switch (action.type) {
    case 'CONTACT_INFO': {
      const newState = {
        ...state,
        contactInfo: {
          ...state.contactInfo,
          ...action.payload.contactInfo
        }
      };

      return newState;
    }
    default: return state;
  }
}

const reducers = combineReducers({
  reducer
})

const store = createStore(
  reducers
);


const updateContactInfo = (payload) => ({
  type: 'CONTACT_INFO', payload
})

const mapStateToProps = state => {
  return {
    contactInfo: state.reducer.contactInfo
  }
}

const mapDispatchToProps = dispatch => ({
  updateContactInfo: payload => dispatch(updateContactInfo(payload))
})

class _App extends Component {

  constructor(props) {
    super(props);

    this.state = {...this.props}
    
    this.updateContactInfo = this.props.updateContactInfo;
  }
  
  static getDerivedStateFromProps (props, state) {

    return {...props}
  }
  
  onChangeInfo ({target: {name, value}}, action) {
    const contactInfo = { contactInfo: {[name]: value}};

    if (action === 'CHANGE') {
      this.updateContactInfo(contactInfo);
    }

  }

  render() {
    const { firstName, address, city } = this.state.contactInfo;
    
    return <div>
       <div>
        <input placeholder=" " type="text" name='firstName' value={firstName} onChange={(e) => this.onChangeInfo(e, 'CHANGE')} required id="" />
        <div className="placeholder"><span>First &amp; last name</span></div>
    </div>
    <div>
        <input placeholder=" " type="text" name="address" value={address} onChange={(e) => this.onChangeInfo(e, 'CHANGE')} required id="" />
        <div className="placeholder"><span>Address</span></div>
    </div>
    <div>
        <input placeholder=" " type="text" name="city" value={city} onChange={(e) => this.onChangeInfo(e, 'CHANGE')} required id="" />
        <div className="placeholder"><span>City</span></div>
    </div>
    {JSON.stringify(this.state)}
    </div>
  }
}

const App = connect(mapStateToProps, mapDispatchToProps)(_App)

ReactDOM.render(
    <Provider store={store}>
      <App />
    </Provider>,
    document.getElementById('root')
  );
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.10.1/polyfill.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/redux@4.0.5/dist/redux.js"></script>
<script src="https://unpkg.com/react-redux@latest/dist/react-redux.js"></script>
<div id="root"></div>

答案 2 :(得分:0)

好问题。

在给您答案之前,我必须指出几件事。在任何应用程序中,通常存在两种状态:长期状态和短暂状态(也称为短暂状态)。 Redux旨在充当您的容器,以放置您的所有长期状态,这些长期状态是您应用程序中不同部分通常关心的。

话虽如此,我可以看到您在应用程序中唯一要做的就是用用户输入来更新状态。我敢打赌,当用户单击“提交”按钮时,您可以使用该状态执行某些操作。如果是这种情况,那么根据定义,输入是短暂的,我将输入状态全部放在Redux中。相反,当用户提交表单时,我只会触发1个操作。

<form onSubmit={onSubmitHandler}>
  <input name="name" type="text" />
  <input name="hobby" type="text" />
  <button type="submit" />
<form />

------
// this is slight pseudo-code, but hopefully you get the gist
const onSubmitHandler = (event) => {
 const myFields = // get fields from event object.
 dispatch({type: 'SOME-ACTION', fields: myFields})
}

我还建议您考虑更改总体上对行为建模的方式。您可以看一下video,它超出了我的意思。