skip to Main Content

I’m having issues with my login/logout and then showing data in a form. If I restart my server and login without logging out it works and shows data. However if I log in, then log out, and the in again, it seems like the data in useEffect takes too long and doesn’t show in the form.

This is my login:

export const login = (email, password ) => async dispatch => {
    const config = {
        headers: {
            'Content-Type':'application/json'
        }
    }
    const body = JSON.stringify({email, password})
    try{
        const res = await axios.post('/api/auth/login', body, config)
        dispatch({
            type: LOGIN_SUCCESS,
            payload: res.data
        })

        dispatch(loadUser())
    } catch (e){
        let errors = e.response.data;
        console.log(errors)

        if(errors) {
            dispatch(setAlert(errors.message, 'danger'))
        }
        dispatch({
            type: LOGIN_FAIL
        })
    }
}

This is my logout:

export const logout = (history) => dispatch => {
    dispatch ({ type: CLEAR_PROFILE })
    dispatch ({ type: LOGOUT })
    history.push('/proveedores')
}

This is how i get data:

export const getCurrentProfile = () => async dispatch => {
    try{
        const res = await axios.get('/api/usuarios/me')
        dispatch({
            type: GET_PROFILE,
            payload: res.data
        })
    } catch (e) {
        dispatch({
            type: PROFILE_ERROR,
            payload: {msg: e.response.message}
        })
    }

}

And this is my component:

useEffect(() => {
        getCurrentProfile()
        setFormData({
             nombres: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.nombres ,
             apellidos: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.apellidos ,
             email: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.email ,
             telefono: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.telefono ,
             ruc: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.ruc ,
             razon_social: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.razon_social ,
             sector_negocio: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.sector_negocio,
             bio: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.bio ,
             direccion: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.direccion ,
             facebook: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.social.facebook ,
             twitter: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.social.twitter ,
             linkedin: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.social.linkedin ,
             instagram: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.social.instagram ,
             website: loading || !profile || profile == undefined || profile == '' || profile == null ? '' : profile.data.website ,

         })   

         let completeFieldsCounter = 0

         if(user){

            if(user.nombres !== '' && user.nombres !== null && user.nombres !== undefined) completeFieldsCounter++
            if(user.apellidos !== '' && user.apellidos !== null && user.apellidos !== undefined) completeFieldsCounter++
            if(user.email !== '' && user.email !== null && user.email !== undefined) completeFieldsCounter++
            if(user.telefono !== '' && user.telefono !== null && user.telefono !== undefined) completeFieldsCounter++
            if(user.ruc !== '' && user.ruc !== null && user.ruc !== undefined) completeFieldsCounter++
            if(user.razon_social !== '' && user.razon_social !== null && user.razon_social !== undefined) completeFieldsCounter++
            if(user.sector_negocio !== '' && user.sector_negocio !== null && user.sector_negocio !== undefined) completeFieldsCounter++
            if(user.bio !== '' && user.bio !== null && user.bio !== undefined) completeFieldsCounter++ 
            if(user.direccion !== '' && user.direccion !== null && user.direccion !== undefined) completeFieldsCounter++

        }

        if(completeFieldsCounter == 9 ){
            setShow(false)
        } else {
            setShow(true)
        }

    }, [loading])


return loading && !profile ? <Spinner /> : <Fragment>
    <Modal centered show={show} onHide={handleClose}>
        <Modal.Header closeButton>
            <Modal.Title>Recordatorio <i class="modal-bulb-profile far fa-lightbulb"></i></Modal.Title>
        </Modal.Header>
        <Modal.Body>Para poder figurar como proveedor necesitas completar los datos de tu empresa.</Modal.Body>
        <Modal.Footer>
            <button onClick={handleClose}>Cerrar</button>
        </Modal.Footer>
    </Modal>
    <div className="perfil-proveedor">
        <div className="perfil-saludo">
            <h1>Hola, <span>{nombres+' '+apellidos}</span></h1>
        </div>
        <ProgressBar animated now={emptyFieldsCounter} />
        <div className="perfil-progress-status">
            <p>Tu perfil está al {emptyFieldsCounter} %</p>
        </div>
        <div className="perfil-editar-btn">
            <button onClick={() => disableBtn()}>Editar</button>
        </div>
        <Alert/>
        <div className="perfil-form">
            <form onSubmit={e => onSubmit(e)}>
                <div className="perfil-datos">
                    <div className="perfil-field perfil-email" >
                        <label className="col-5 no-margin no-padding" htmlFor="email">Email</label>
                        <input className="col-7 no-margin no-padding" type="text" name="email" disabled={disabled} value={email} onChange={ (e) => onChange(e)}/>
                    </div>
    </div>
                </form>
            </div>
        </div>
        </Fragment>

I’m not pasting my whole component because it’s a lot but it just repeats the inputs.

I need a way to fix my missing data when logging in after logging out.

2

Answers


  1. I had the same issue before. I think there is an issue regarding what you put in the array at the end of your useEffect function. But hard to tell precisely from what’s given.

    First of all, it only shows Redux actions, so check the reducers regarding your login/out cases. That’s because you put loading in the useEffect array, meaning that it’ll trigger the useEffect whenever your loading state changes, so maybe your loading state is not stable or there’s something wrong with it. That can be one reason why your useEffect loading for a long time(running over and over again). – IF you intentionally put loading there for some reasons.

    Next, try to remove loading from the array and put only getCurrentProfile inside the array (not as function, but as I wrote).

      useEffect(() => {
        getCurrentProfile();
      }, [getCurrentProfile])
    

    it means that the useEffect will not gonna be triggered unless getCurrentProfile is called = use once.

    From React Effect Hook Documentation

    If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders. Learn more about how to deal with functions and what to do when the array changes too often.

    If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. This isn’t handled as a special case — it follows directly from how the dependencies array always works.

    If you pass an empty array ([]), the props and state inside the effect will always have their initial values. While passing [] as the second argument is closer to the familiar componentDidMount and componentWillUnmount mental model, there are usually better solutions to avoid re-running effects too often. Also, don’t forget that React defers running useEffect until after the browser has painted, so doing extra work is less of a problem.

    We recommend using the exhaustive-deps rule as part of our eslint-plugin-react-hooks package. It warns when dependencies are specified incorrectly and suggests a fix.

    Good luck with your project and happy coding!

    Login or Signup to reply.
  2. For brief, this caused by using wrong useEffect call and its dependencies. Because each part of logics in your form need to handle separately, you will need multiple effects as below:

    First, if you want to get profile when user state change (from log out to log in), you will need an effect to run getCurrentProfile when user logged in.

    useEffect(() => {
      // User has been logged in
      if (loggedIn) getCurrentProfile();
    }, [loggedIn]);
    

    Then you need another effect to listen to profile change, from above when user’s profile has been fetched successfully, to populate form fields as expected:

    useEffect(() => {
      setFormData({
        ... // see as above
      });
    }, [profile]);
    

    Finally, to setShow modal based on completed fields, I suggest using another useEffect for checking these user data (which might be your form data, as I predicted):

    useEffect(() => {
      let completeFieldsCounter = 0;
      if (user) {
        ... // see snippets above
      }
      if(completeFieldsCounter == 9 ){
        setShow(false)
      } else {
        setShow(true)
      }
    }, [user]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search