Redux - 添加/删除输入字段on

时间:2017-06-13 11:28:58

标签: javascript reactjs redux react-router react-redux

我正在尝试在点击两个按钮时添加和删除下拉字段:

  • 一个“添加”按钮,添加/创建一个新的下拉字段(预定义了选项和值)
  • 每个下拉列表旁边的“删除”按钮(为了逐个删除它们)

这是一个多页应用,所以我使用React Router从一个页面导航到另一个页面 - 所以为了保持我正在使用Redux的状态。

我设法在点击按钮时添加和删除下拉字段 - 但我面临两个问题:

  1. 我要将下拉菜单保存到商店,所以如果我导航到另一个页面并返回,则添加的下拉列表将从页面中删除
  2. 无论何时添加新的下拉列表,都会重置选项的选项
  3. 到目前为止,这是我的代码:

    import React from 'react'
    import { connect } from 'react-redux'
    import { addData, saveSelect, removeSelect } from '../actions.js'
    
    class AddSelectField extends React.Component {
      constructor(props){
        super(props);
    
        this.state = {
          inputSelect: []
        }
      }
    
      saveData = (e) => {
        let data = {}
        data[e.target.name] = e.target.value
    
        this.context.store.dispatch(
          addData(data)
        )
      }
    
      addInput = () => {
        const inputSelect = this.state.inputSelect.concat(this.renderDropDown);
        this.setState({ inputSelect });
    
        this.context.store.dispatch(
          saveSelect(this.state.inputSelect)
        )
      }
    
      removeInput = (item) => {
        let index = this.state.inputSelect.indexOf(item);
        let newInputSelect = this.state.inputSelect;
        newInputSelect.splice(index,1);
    
        this.setState({
          inputSelect: newInputSelect
        });
    
        this.context.store.dispatch(
          removeSelect(newInputSelect)
        )
      }
    
      renderDropDown = (el, index) => {
        return(
          <div>
            <select
              key={index}
              name={'document-'+ index}
              value={'document-'+ index}
              onChange = {this.saveData}
            >
              <option value="0">Please Select</option>
              <option value="1">Australia</option>
              <option value="2">France</option>
              <option value="3">United Kingdom</option>
              <option value="4">United States</option>
            </select>
    
            <button onClick={ this.removeInput }>Remove</button>
          </div>
        )
      }
    
      render(){
        return(
          <div>
            <button onClick={ this.addInput }>Add</button>
    
            <div className="inputs">
              {this.state.inputSelect.map(this.renderSelect)}
            </div>
          </div>
        )
      }
    }
    
    class AccountUpgrade extends React.Component {
    
      constructor(props) {
        super(props);
      }
    
      continueClick() {
        this.context.router.push('/AccountUpgrade/Confirmation/')
      }
    
      render(){
        return (
          <div>
            <div className="row">
                <AddSelectField />
    
                <ButtonRow
                primaryProps={{
                  children: 'Continue',
                  onClick: this.continueClick.bind(this)
                }} />
            </div>
          </div>
        )
      }
    }
    
    AccountUpgrade.contextTypes = {
      store: React.PropTypes.object.isRequired,
      router: React.PropTypes.object.isRequired
    }
    
    const mapStateToProps = (state) => {
      return {
        store: state.EligibleAbout
      }
    }
    
    const EligibleAbout = connect(mapStateToProps)(AccountUpgrade)
    
    export default EligibleAbout
    

    action.js

    export const ADD_DATA = 'ADD_DATA'
    export const ADD_SELECT = 'ADD_SELECT'
    export const REMOVE_SELECT = 'REMOVE_SELECT'
    
    
    export function addData(data) {
      return { type: ADD_DATA, data }
    }
    
    
    export function saveSelect(data) {
      return { type: ADD_SELECT, data }
    }
    
    export function removeSelect(data) {
      return { type: REMOVE_SELECT, data }
    }
    

    reducer.js

    import ObjectAssign from 'object.assign'
    import { combineReducers } from 'redux'
    import { ADD_DATA, ADD_SELECT, REMOVE_SELECT } from './actions'
    
    function EligibleAbout(state = {}, action){
      switch (action.type){
        case ADD_DATA:
          return ObjectAssign({}, state, action.data)
        case ADD_SELECT:
            return ObjectAssign({}, state, action.data)
        case REMOVE_SELECT:
          return ObjectAssign({}, state, action.data)
        default:
          return state
      }
    }
    
    const FormApp = combineReducers({
      EligibleAbout
    })
    
    export default FormApp
    

1 个答案:

答案 0 :(得分:1)

您正在管理组件和reducer中的状态。在渲染功能中,您始终从最初为空白的状态获取 inputSelect 的值。您没有使用存储在reducer中的值来进行渲染,这就是为什么你没有让它回来。

不要将 inputSelect 存储在组件状态中。只需将它存储在reducer中并使用reducer中的reduSelect进行渲染。

Content-Type: application/vnd.api+json

更新的Reducer是:

import React, { PropTypes } from 'react'
import { connect } from 'react-redux'
import uuidV4 from 'uuid/v4'


class AddSelectField extends React.Component {
  static propTypes = {
    ids: PropTypes.array,
    removeSelect: PropTypes.func,
    saveSelect: PropTypes.func,
  }
  static defaultProps = {
    ids: [],
  }
  saveData = (e) => {
    // Just do your stuff here.
  }

  addInput = () => {
    this.props.saveSelect(uuidV4())
  }

  removeInput = index => {
    this.props.removeSelect(index)
  }

  renderDropDown = (id, index) => {
    return (
      <div>
        <select
          key={id}
          name={id}
          onChange={this.saveData}
          >
          <option value="0">Please Select</option>
          <option value="1">Australia</option>
          <option value="2">France</option>
          <option value="3">United Kingdom</option>
          <option value="4">United States</option>
        </select>

        <button
          onClick={() => {
            this.removeInput(index)
          }}>
          Remove
        </button>
      </div>
    )
  }

  render() {
    const ids = this.props.ids
    return(
      <div>
        <button onClick={ this.addInput }>Add</button>

        <div className="inputs">
          {ids.map(this.renderDropDown)}
        </div>
      </div>
    )
  }
}

const mapStateToProps = state => {
  const eligibleAbout = state.EligibleAbout
  return {
    ids: eligibleAbout.ids,
  }
}

const EligibleAbout = connect(mapStateToProps, { saveSelect, removeSelect })(AddSelectField)


export default class AccountUpgrade extends React.Component {
  continueClick() {
    // do your stuff here.
  }
  render() {
    return (
      <div>
        <div className="row">
          <EligibleAbout />

        </div>
      </div>
    )
  }
}

如果我去过你的地方,除了国家管理之外,我会这样做。我建议使用immutable将是状态管理的一个很好的选择。

注意:我只实现了添加和删除输入功能。不清楚 saveData 功能要求。