在redux中更新对象的状态。

问题描述 投票:0回答:1

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

/ Reducer


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;
    }
}
reactjs redux react-redux
1个回答
1
投票

我不明白这样做的意义 使用 setState 在此

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/[email protected]/dist/redux.js"></script>
<script src="https://unpkg.com/react-redux@latest/dist/react-redux.js"></script>
<div id="root"></div>

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

而且,在reducer中,根据action.type更新存储。


0
投票

好问题。

在我给你答案之前,有几件事我必须指出。一般来说,在任何应用程序中都存在2种类型的状态:长期状态和短期(也就是短暂的)状态。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})
}

我还建议你考虑改变你的动作建模方式。你可以看一下这个 视频 这是我的意思。

© www.soinside.com 2019 - 2024. All rights reserved.