Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/416.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Redux-单击添加/删除输入字段_Javascript_Reactjs_Redux_React Router_React Redux - Fatal编程技术网

Javascript Redux-单击添加/删除输入字段

Javascript Redux-单击添加/删除输入字段,javascript,reactjs,redux,react-router,react-redux,Javascript,Reactjs,Redux,React Router,React Redux,我尝试在单击两个按钮时添加和删除下拉字段: 一个“添加”按钮,用于添加/创建新的下拉字段(使用选项和值预定义) 每个下拉列表旁边的“删除”按钮(以便单独删除) 这是一个多页面的应用程序,所以我使用React Router从一个页面导航到另一个页面-所以我使用Redux保持状态 我设法在点击按钮时添加和删除下拉字段,但我面临两个问题: 我正在将下拉列表保存到商店,因此如果我导航到另一个页面并返回,添加的下拉列表将从该页面中消失 每当添加新的下拉列表时,选择的选项都会重置 以下是我目前的代码:

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

  • 一个“添加”按钮,用于添加/创建新的下拉字段(使用选项和值预定义)
  • 每个下拉列表旁边的“删除”按钮(以便单独删除)
这是一个多页面的应用程序,所以我使用React Router从一个页面导航到另一个页面-所以我使用Redux保持状态

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

  • 我正在将下拉列表保存到商店,因此如果我导航到另一个页面并返回,添加的下拉列表将从该页面中消失
  • 每当添加新的下拉列表时,选择的选项都会重置
  • 以下是我目前的代码:

    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
    
    reducer.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 }
    }
    
    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中,并使用inputSelect from 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将是状态管理的一个好选择


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

    你好,Ritesh,谢谢您的回答。你能给我举个例子说明你在代码中的意思吗?saveData是保持选项状态处于选中状态的函数。查看您的代码—只是想知道为什么需要uuid包。没有它不可能完成?我想为每个选择分配唯一的id。UUID仅用于此目的。如果仅需要添加数据来设置所选值,则只需存储与每个选择的唯一id相对应的值。是否可以使用map中的“key”值而不是UUID no?
    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
      }
    }