tutorial react helmet javascript reactjs redux react-router

javascript - tutorial - react helmet ssr



React/Redux: guarde el valor seleccionado enCambiar (2)

Creé un Componente que le permite agregar / quitar un campo desplegable (al hacer clic en dos botones). Estoy usando Redux para mantener el estado del menú desplegable, de modo que cuando navego hacia atrás y adelante (React Router) los desplegables agregados no se pierden.

Ahora también necesito mantener los valores de cada menú desplegable en Cambio. Así que onChange estoy enviando el valor de las listas desplegables al reductor, pero parece que está actualizando todas las listas desplegables a la vez (no individualmente).

¿Algúna idea de cómo arreglar esto?

Aquí está mi código hasta ahora:

Componente

import React from ''react'' import { connect } from ''react-redux'' import uuidV4 from ''uuid-v4'' import { saveSelect, removeSelect, saveSelectValue, incrementCounter, decrementCounter } from ''../actions.js'' class AccountUpgrade extends React.Component { constructor(props) { super(props); } addInput = (counter) => { this.props.saveSelect(uuidV4()) this.props.incrementCounter(counter) } removeInput = (index, counter) => { this.props.removeSelect(index) this.props.decrementCounter(counter) } saveSelectValue = (e) => { let data = {} data = e.target.value this.props.saveSelectValue(data) } renderSelect = (id, index) => { const selectedValue = this.props.selectedValue || '''' const counter = this.props.counter return( <div className="col-12"> <select key={id} name={''document-''+ id} value={selectedValue} onChange = {this.saveSelectValue} > <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, counter) }}>Remove</button> </div> ) } render(){ const ids = this.props.ids || [] const counter = this.props.counter return ( <div> {this.props.counter <= 4 && <button onClick={ this.addInput }>Add</button> } <div className="inputs"> {ids.map(this.renderSelect)} </div> </div> ) } } const mapStateToProps = (state) => { return { store: state.EligibleAbout, ids: state.EligibleAbout.ids, selectedValue: state.EligibleAbout.selectedValue, counter: state.EligibleAbout.counter, } } const EligibleAbout = connect(mapStateToProps, {saveSelect, removeSelect, saveSelectValue, incrementCounter, decrementCounter})(AccountUpgrade) export default EligibleAbout

action.js

export const ADD_SELECT = ''ADD_SELECT'' export const REMOVE_SELECT = ''REMOVE_SELECT'' export const SAVE_SELECT_OPTION = ''SAVE_SELECT_OPTION'' export const INCREMENT_COUNTER = ''INCREMENT_COUNTER'' export const DECREMENT_COUNTER = ''DECREMENT_COUNTER'' export function saveSelect(data) { return { type: ADD_SELECT, data } } export function removeSelect(data) { return { type: REMOVE_SELECT, data } } export function saveSelectValue(data) { return { type: SAVE_SELECT_OPTION, data} } export function incrementCounter(data) { return { type: INCREMENT_COUNTER, data } } export function decrementCounter(data) { return { type: DECREMENT_COUNTER, data } }

reducer.js

import { combineReducers } from ''redux'' import { ADD_SELECT, REMOVE_SELECT, SAVE_SELECT_OPTION } from ''./actions'' function EligibleAbout(state = { ids: [], counter: 0, selectedValue: ''Please select''}, action = {}){ switch (action.type){ 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)), } case SAVE_SELECT_OPTION: return { ...state, selectedValue: action.data } case INCREMENT_COUNTER: return { ...state, counter: state.counter + 1 } case DECREMENT_COUNTER: return { ...state, counter: state.counter - 1 } default: return state } } const FormApp = combineReducers({ EligibleAbout }) export default FormApp


Como necesita mantener el valor seleccionado para cada id o menú desplegable, el mejor enfoque sería mantener una matriz de objetos con objetos que tengan propiedades de id y de value lugar de tener ids matriz de cadena. Entonces deberás cambiar tu código en algo como esto. No probé el código, así que avíseme en los comentarios si tiene algún problema.

class AccountUpgrade extends React.Component { constructor(props) { super(props); } addInput = () => { this.props.saveSelect({id:uuidV4()}) } removeInput = (index) => { this.props.removeSelect(index) } saveSelectValue = (e, id) => { let data = {} data.id = id; data.value = e.target.value this.props.saveSelectValue(data) } renderSelect = (selection, index) => { const selectedValue = selection.value || ''''; const id = selection.id; return( <div className="col-12"> <select key={id} name={''document-''+ id} value={selectedValue} onChange = {(e) => this.saveSelectValue(e, id)} > <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 selections = this.props.selections || [] return ( <div> <button onClick={ this.addInput }>Add</button> <div className="inputs"> {selections.map(this.renderSelect)} </div> </div> ) } } const mapStateToProps = (state) => { return { store: state.EligibleAbout, selections: state.EligibleAbout.selections, } }

También necesita modificar su reductor.

function EligibleAbout(state = { selections: [] } , action = {}){ switch (action.type){ case ADD_SELECT: return { ...state, selections: [].concat(state.selections, action.data), } case REMOVE_SELECT: return { ...state, selections: state.selections.filter((selection, index) => (index !== action.data)), } case SAVE_SELECT_OPTION: return { ...state, selections: state.selections.map((selection) => selection.id === action.data.id ? action.data : selection) } default: return state } }


Solo está almacenando un valor seleccionado del que todos leen. Deberá dar a cada uno una identificación de algún tipo y guardar / recuperar su estado seleccionado específicamente. Algo como:

case SAVE_SELECT_OPTION: return { ...state, selectedValues: { [action.selectID]: action.data } }

Por supuesto, deberá actualizar su despacho y sus acciones en consecuencia.