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.