【问题标题】:Change redux state based on onChange event value根据 onChange 事件值改变 redux 状态
【发布时间】:2019-12-12 08:20:49
【问题描述】:

我正在使用 redux,并且我的状态为空字符串值。必须使用输入 onChange 事件填充每个空键。假设我想更改“business_selected”键,该功能应该是什么样的?这是我的状态:


const initialState = {

        user: {},
        applications: [
            {
                companyFlow: {
                    stage1: {
                        business_activity: "",
                        business_selected: ""
                    },

                    stage2: {
                        legal_name: "",
                        registration_number: "",
                        business_website: "",
                        incorporation_date_text: "",
                        legal_form: ""
                    }
                }
            }
        ]
};

export default function changeInput(state = initialState, action) {
  switch (action.type) {
    case CHANGE_INPUT:
      return {
        // ??????
      };
    default:
      return state;
  }
}

【问题讨论】:

    标签: javascript reactjs redux


    【解决方案1】:

    onChnage 值应该存储在本地状态而不是 redux 状态。 理想情况下,只有全局值应该存储在 redux 状态。

    【讨论】:

      【解决方案2】:

      抛开对深度嵌套状态变量的担忧(避免使用recommended),并理所当然地认为让这些变量全局可访问的理由是理所当然的(尽管这似乎是selectors 的一个很好的用例),如果您在最基本的层面上问的是如何将调度某些操作绑定到组件事件(例如onChangeonKeyUp 等属性),我建议您参考official tutorial 关于该主题.

      但是,以下示例非常简单,展示了一般概念。您可以自行决定在状态复杂性和组件灵活性之间进行扩展、重新平衡。

      //dependencies
      const { render } = ReactDOM,
            { createStore } = Redux,
            { connect, Provider } = ReactRedux
            
      //store initialization
      const defaultState = {
              businessActivity: {
                options: ['operation', 'investing', 'financing'],
                currentValue: ''
              },
              legalName:{
                currentValue:''
              }
            },
            appReducer = (state=defaultState, action) => {
              switch(action.type){
                case 'SET_PARAM': {
                  const {payload:{param,val}} = action           
                  return {...state, [param]:{...state[param], currentValue: val}}
                }
                default: return state
              }     
            },
            store = createStore(appReducer) 
      //arbitrary dropdown component
      const DropDown = ({onParamChange, param, options, val}) => (
        <select 
          param={param} 
          onChange={e => (val=e.target.value, onParamChange(param,val))}
        >
          {['',...options].map((opt,key) => <option value={opt} key={key} selected={opt==val}>{opt}</option>)}
        </select>
      )
      //dropdown container
      var mapStateToProps = (state, {param}) => ({
              val:state[param]['currentValue']||'',
              options:[...state[param]['options']]
            }),
            mapDispatchToProps = (dispatch, {param,val}) => ({onParamChange: (param,val) => dispatch({type:'SET_PARAM',payload:{param,val}})})
      const DropDownContainer = connect(mapStateToProps, mapDispatchToProps)(DropDown)
      //arbitrary input component
      const InputBox = ({onParamInput, param, val}) => (
        <input 
          param={param} 
          val={val}
          placeholder={val}
          onKeyUp={e => (val=e.target.value, onParamInput(param,val))}
        ></input>
      )
      //input box container
      var mapStateToProps = (state, {param}) => ({val: state[param]['currentValue']||''}),
            mapDispatchToProps = (dispatch, {param,val}) => ({onParamInput: (param,val) => dispatch({type:'SET_PARAM', payload:{param,val}})})
      const InputBoxContainer = connect(mapStateToProps,mapDispatchToProps)(InputBox)
      //resulting state mirror
      const PrintOut = ({activity,name}) => <div>Current business activity is {activity||'_'} and legal name is {name||'_'}</div>
      //print out container
      var mapStateToProps = ({businessActivity:{currentValue:activity},legalName:{currentValue:name}}) => ({activity,name})
      const PrintOutContainer = connect(mapStateToProps)(PrintOut)
      //provider
      render(
        <Provider store={store}>
          <DropDownContainer param="businessActivity" />
          <InputBoxContainer param="legalName" />
          <PrintOutContainer />
        </Provider>,
        document.getElementById('root')
      )
      &lt;script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"&gt;&lt;/script&gt;&lt;script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"&gt;&lt;/script&gt;&lt;script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.4/redux.min.js"&gt;&lt;/script&gt;&lt;script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.1.1/react-redux.min.js"&gt;&lt;/script&gt;&lt;div id="root"&gt;&lt;/div&gt;

      【讨论】:

        【解决方案3】:

        通常onChange 使用component 本身中的本地状态进行处理,但如果您想在redux 中执行此操作,您可以执行以下操作。

        export default function changeInput(state = initialState, action) {
          switch (action.type) {
            case CHANGE_INPUT:
              return {
               ...state,
               applications: state.applications.map(application => {
                return Object.assign({}, application, {
                 ...application,
                 companyFlow: {
                  ...application.companyFlow,
                  stage1: {
                    ...application.companyFlow.stage1,
                    business_selected: action.payload
                  }
                 }
                }
               return application
              });
            default:
              return state;
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2021-05-28
          • 2019-04-29
          • 1970-01-01
          • 2021-07-02
          • 2017-04-04
          • 2020-12-21
          • 2021-12-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多