Redux - add/remove 输入字段 onclick

Redux - add/remove input field onclick

我正在尝试通过单击两个按钮来添加和删除下拉字段:

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

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

  1. 我正在努力将下拉菜单保存到商店中,所以如果我导航到另一个页面并返回,添加的下拉菜单将从页面中消失
  2. 每当添加新的下拉菜单时,选择的选项都会重置

到目前为止,这是我的代码:

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

您正在管理组件和减速器中的状态。在渲染函数中,您总是从最初为空白的状态中获取 inputSelect 的值。您没有将存储在 reducer 中的值用于渲染目的,这就是您返回时没有得到它的原因。

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

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

更新的 Reducer 是:

function eligibleAbout(state = { ids: [] }, action = {}){
  switch (action.type) {
    case ADD_DATA:
    // set according to requirement.
    case ADD_SELECT:
      return {
        ...state,
        ids: [].concat(state.ids, action.data),
      }
    case REMOVE_SELECT:
      return {
        ...state,
        ids: state.ids.filter((id, index) => (index !== action.data)),
      }
    default:
      return state
  }
}

如果我在你那里,除了状态管理,我会这样做。我建议使用 immutable 将是状态管理的一个不错的选择。

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