Home > OS >  usestate in react for setting state
usestate in react for setting state

Time:06-12

Hi in my application we are using initialstate where the application sample data will be defined and using the context for state management, below is my sample initial state:

-

creditCard: {
           isSaved: false,
           lastFourDigits: "1235",
           loading: false,
           cardholder: "",
           cardnumber: "",
           cardmonth: "",
           cardyear: "",
           cardcvv: "",
         },
       etc:{}....

and in my component i am using usestate for setting the data as below :

 const { state } = useContext(StateContext);
  const [cardholder, setcardholder] = useState("");
  const [cardnumber, setcardnumber] = useState("");
  const [cardmonth, setcardmonth] = useState("");
  const [cardyear, setcardyear] = useState("");
  const [cardcvv, setcardcvv] = useState("");

and in onchange i am setting state as below:

<TextField
                    name="cardmonth"
                    label="MM"
                    error={errors.cardmonth}
                    value={cardmonth}
                    onChange={onChange}
                    onBlur={validateInput}
                    helperText={errors.cardmonth && "Invalid month"}
                    className={classes.expiryDateInputs}
                  />
onchange=()=>{
  let cardMonth = /^0[1-9]|1[0-2]/.test(e.target.value);
        if (cardMonth === true) {
          setcardmonth(e.target.value.replace(/\D/g, "").slice(0, 2));
          setErrors({ ...errors, cardmonth: false });
        } else {
          setErrors({ ...errors, cardmonth: true });
        }
        if (state.creditCard.cardyear !== "") {
          validateExpiryDate();
        }

}

is this the correct way what i am doing, can anyone please tell me what i am doing in onchange and in html code is correct or not..

CodePudding user response:

If you need to validate your input inside onChange this code is perfectly fine. But ,It's not a good idea to validate input on the onChange event . Put your validation logic inside onBlur or onSubmit events and in onChange event , simply set state to event value. also, I would recommend better naming convention.

onChange={(e)=>handleOnChange(e)}

///////////

handleOnChange=(event)=>{
          setcardmonth(event.target.value);
}

// move your validation logic to onBlur or onSubmit

CodePudding user response:

Seems like you have defined your initialState up on the context/global level, but at the same time redefined it in one of your local component with a bunch more individual state:

  const { state } = useContext(StateContext);
  const [cardholder, setcardholder] = useState("");
  const [cardnumber, setcardnumber] = useState("");
  const [cardmonth, setcardmonth] = useState("");
  const [cardyear, setcardyear] = useState("");
  const [cardcvv, setcardcvv] = useState("");

That effectly makes your onChange function only update the state you redefined in your component, and it does not affect your context state, and won't update UI if the UI is dependent on context state.:

onchange=()=>{
  let cardMonth = /^0[1-9]|1[0-2]/.test(e.target.value);
        if (cardMonth === true) {
          setcardmonth(e.target.value.replace(/\D/g, "").slice(0, 2));
          setErrors({ ...errors, cardmonth: false });
        } else {
          setErrors({ ...errors, cardmonth: true });
        }
        if (state.creditCard.cardyear !== "") {
          validateExpiryDate();
        }

Meaning you are doing some extra unnecessary work by simplying redefinning things/states.

You can do one of the three ways:

  1. Go straight for local state without global state, and if some child components needs them, you can just pass props and drill them down;
  2. Or combine global and local state: for those states that need to be shared between different non-related components, you define it in global level, ie. your initialstate, for those that doesn't, put them in a local state;
  3. Or go straight for global state.

On the straight global state approach, you can combine useReducer with context, and that makes updating state more managable(considering your initialstate is relatively complex), otherwise, you can pass setState function:

const { state, setState } = useContext(StateContext); // <- pass down setState from context as well

onchange=()=>{
  let cardMonth = /^0[1-9]|1[0-2]/.test(e.target.value);
        if (cardMonth === true) {
          setState(); // <- your update logic
        } else {
          setState(); // <- your update logic
        }
        if (state.creditCard.cardyear !== "") {
          validateExpiryDate();
        }
  • Related