Emre Sert
Emre Sert

Reputation: 330

React Hooks Second Click and Change State Values

I have a problem and I wonder what happend. My code is working fine and I change state values with Hooks. While everything is Ok , in my console I am facing previous state value in first click the button. When I click the button second time, state values start to come correctly. Is it logical thing according to Hooks or is there anything which I missed ?

My example Login.tsx :

import React, { useState, useContext, useEffect } from 'react';
import { Input, Button, DropDownMenu, Checkbox } from 'oneframe-react';
import { useTranslation } from 'react-i18next';

export const LoginPart = (props: any) => {

    interface IState {
        pageLanguage: any;
        email: string;
        password: string;
        rememberMeCheck: boolean;

    }


    const initialState: IState = {
        email: '',
        password: '',
        pageLanguage: '',
        rememberMeCheck: false,

    };

    const [leftPartState, setState] = useState<any>(initialState);
    const { t, i18n } = useTranslation();


    const handleChange = (e: any) => {
        setState((prevState: any) => ({
            ...prevState,
            [e.target.name]: e.target.value,
        }));
    };

    const handleCheckBoxChange = (e: any) => {
        setState( (prevState : any) => ({
            ...prevState,
            [e.target.name]: e.target.checked,
        }));
    };


    const handleSubmit: any = (e: Event) => {

      // fallowing code changes values but console situations are like : 
      // {email: "", password: "", pageLanguage: "", rememberMeCheck: false}   -> first click and print 
      // {email: "", password: "", pageLanguage: "eng", rememberMeCheck: true} -> second click and print
     setState({...leftPartState, email: '', password: '',rememberMeCheck:true, pageLanguage : localStorage.getItem("userlanguage")})
        e.preventDefault();
        console.log(leftPartState)
    }

    const handleClick : any = (selectedlang: any) => {

        leftPartState.pageLanguage = selectedlang.Name
        setState({...leftPartState, pageLanguage :leftPartState.pageLanguage  })
         i18n.changeLanguage(selectedlang.Name) 
        localStorage.setItem("userlanguage", selectedlang.Name)  
    }

    useEffect(() => {

    },[leftPartState])


    const renderLoginPart = () => {
        return (
            <div className="render-login-part-container">
                <form onSubmit={() => handleSubmit(event)}>

                    <DropDownMenu
                        className="select-language"
                        fullWidth={false}
                        options={{
                            data: [
                                {
                                    Name: 'tr',
                                    Id: 1,
                                },
                                {
                                    Name: 'eng',
                                    Id: 2,
                                }
                            ],
                            displayField: 'Name',
                            displayValue: 'Id',
                            selected: 1
                        }}
                        onClick={(event : Event) => handleClick(event)}
                    />

                    <Input
                        id="basicInput"
                        name="email"
                        caption={t('email')}

                        type="text"
                        onChange={handleChange}
                        value={leftPartState.email}
                        rightAdornments={() => {
                            return <i className="fal fa-envelope mr-1"></i>;
                        }}
                        className="login-input"

                    />

                    <Input
                        id="basicInput"
                        name="password"
                        caption={t('password')}
                        type="password"
                        onChange={handleChange}
                        value={leftPartState.password}
                        rightAdornments={() => {
                            return <i style={{ cursor: "pointer" }} className="far fa-eye-slash"></i>;
                        }}
                        className="login-input mt-2"
                    />
                    <div className="container">
                        <div className="row rememberme-and-forgotpassword-container">
                            <div>

                                {/* Not: Checked özelliği ayarlanmalı */}
                            <Checkbox
                                    id={'rememberMeCheck'}
                                    name={'rememberMeCheck'}
                                    label={t("rememberMe")}
                                    checked={leftPartState.rememberMeCheck?true:false}
                                    onChange={handleCheckBoxChange}
                                    className="rememberme-checkbox"
                                />
                            </div>
                            <div>
                                <p className="forgot-password-text">{t("forgotPassword")}</p>
                            </div>
                        </div>
                    </div>

                    <Button
                        type="submit"
                        text={t("login")}
                        variant={'text'}
                        className={'custom-style-text-button'}
                        fullWidth
                    />
                </form>
            </div>
        )
    }

    return (
        <span>
            {renderLoginPart()}
        </span>
    )
}


export default connect((store: any) => ({ oneframe: store }))(LoginPart) as any;

Upvotes: 1

Views: 2323

Answers (1)

Atin Singh
Atin Singh

Reputation: 3690

Setting a state is asynchronous in nature. You will not get the updated state just after setting it. You can use useEffect hook to get updated value of state everytime it changes -

const handleSubmit: any = (e: Event) => {

  // fallowing code changes values but console situations are like : 
  // {email: "", password: "", pageLanguage: "", rememberMeCheck: false}   -> first click and print 
  // {email: "", password: "", pageLanguage: "eng", rememberMeCheck: true} -> second click and print
 setState({...leftPartState, email: '', password: '',rememberMeCheck:true, pageLanguage : localStorage.getItem("userlanguage")})
    e.preventDefault();
    console.log(leftPartState)
}

useEffect(() => {
   console.log(leftPartState);
}, [leftParState]);

Upvotes: 3

Related Questions