Reputation: 115
There is a base that contains text from inputs:
let data={
textInput:"",
inputInfo:{size:""},
};
export const loginReducer=(state=data,action)=>{
switch (action.type) {
case "ChangeInputInfoSize":
if (Number(action.size)|| action.size==="" ){
let Statecopy={...state};
Statecopy.inputInfo.size=action.size;
return {...Statecopy};
}else {
return state
}
default:
return state;
}
}
export const ChangeInputInfoSizeAC=(size)=>({
type:"ChangeInputInfoSize",
size
});
As well as the component and its container:
import React from "react"
import {connect} from "react-redux";
import {DataFilling} from "./DataFilling";
import {ChangeInputInfoSizeAC} from "../store/loginReducer";
let MapStateToProps=(state)=>{
return {
inputInfo:state.loginReducer.inputInfo,
textInput:state.loginReducer.textInput
}
};
export const DataFillingContainer=connect(MapStateToProps,{ChangeInputInfoSizeAC})(DataFilling)
Component:
import React from "react"
export let DataFilling = (props) => {
let ChangeInputInfoSizeFunc = (e) => {
props.ChangeInputInfoSizeAC(e.target.value)
};
<input placeholder="size" value={props.inputInfo.size} onChange={ChangeInputInfoSizeFunc} />
}
When you try to fill the field, there is no change in the field, but if you replace inputInfo.size with textInput everywhere, then everything will work. What needs to be changed in the first option for it to work?
Upvotes: 0
Views: 41
Reputation: 719
I guess problem is in reducer where creating Statecopy
let Statecopy={...state};
Statecopy.inputInfo.size=action.size;
In first line let Statecopy={...state}
will create a new object {textInput, inputInfo}
but in second line Statecopy.inputInfo
actually referencing to the old inputInfo, so it overwrite size
in old inputInfo
and keep its reference unchanged.
I recommend make states flat as far as possible or make sure creating new state.
let Statecopy={...state,inputInfo:{size:action.size}};
In addition, you can do few improvement to your code by following these steps:
Camel case naming is Javascript convention, so instead of let Statecopy
write let stateCopy
Dispatch type convention is uppercase separated with underlines, so instead of "ChangeInputInfoSize"
write "CHANGE_INPUT_INFO_SIZE"
When declaring a function use const
because you don't want accidentally overwrite a function, so const ChangeInputInfoSizeFunc = (e) => {...
is correct. This is true for export const DataFilling
as well.
For a controlled component like DataFilling
only dispatch the final state, so onChange
event will save value in a local state, then an onBlur
event dispatch the result to reducer.
Limit declaring new variables as far as possible, so in reducer you don't need stateCopy
,
Make reducer initial state a const
variable, you don't want overwrite it.
in if (Number(action.size)|| action.size==="" )
first part will be a number but second part will be an empty string. Because of consistency and preventing future bugs make both same. Also you can do this validation before dispatching size
to the reducer.
Hopefully, all these recommendations will help to avoid future bugs
Upvotes: 1
Reputation: 115
I had to do deep copy
case "ChangeInputInfoSize":{
if (Number(action.size)|| action.size==="" ){
let copyState = {...state};
copyState.inputInfo = {...state.inputInfo};
copyState.inputInfo.size=action.size
return {...copyState};
}else {
return state
}
}
Upvotes: 0