Home > Software engineering >  Why can't I access data after fetching?
Why can't I access data after fetching?

Time:06-10

I'm trying to keep session stayed logged in after refreshing the browser. The user data that is being fetched is not rendering after being fetched. The console is saying "Cannot read properties of undefined (reading 'user'). This is my code for the login/sign up page.

The data I'm trying to access is in the picture below:

enter image description here

enter image description here

(Auth.js)

const Auth = () => {
    const navigate = useNavigate();
    const dispatch = useDispatch();
    const [isSignup, setIsSignup] = useState(false);
    const [inputs, setInputs] = useState({
        name: "",
        username: "",
        email: "",
        password: ""
    })

    const handleChange = (e) => {
        setInputs(prevState => {
            return {
                ...prevState,
                [e.target.name]: e.target.value
            }
        })
    }

     const sendRequest = async (type = '') => {
        const res = await axios.post(`/user/${type}`, {
            name: inputs.name,
            email: inputs.email,
            username: inputs.username,
            password: inputs.password,
        }).catch(error => console.log(error))
        const data = await res.data;
        console.log(data)
        return data;
    }

    const handleSubmit = (e) => {
        e.preventDefault()
        console.log(inputs)
        if (isSignup) {
            sendRequest("signup")
                .then((data) => {
                dispatch(authActions.login());
                localStorage.setItem('userId', data.user._id);
                navigate("/posts");
                });
        } else {
            sendRequest("login")
                .then((data) => {
                dispatch(authActions.login());
                localStorage.setItem('userId', data.user._id);
                navigate("/posts");
                });
        }
    }

Redux store file

const authSlice = createSlice({
    name: "auth",
    initialState: { isLoggedIn: false },
    reducers: {
        login(state) {
            state.isLoggedIn = true
        },
        logout(state) {
            state.isLoggedIn = false
        }
    }
})

export const authActions = authSlice.actions

export const store = configureStore({
    reducer: authSlice.reducer
})

CodePudding user response:

Chaining promises using .then() passes the resolved value from one to the next. With this code...

sendRequest("...")
  .then(() => dispatch(authActions.login()))
  .then(() => navigate("/posts"))
  .then(data => localStorage.setItem('token', data.user))

You're passing the returned / resolved value from navigate("/posts") to the next .then() callback. The navigate() function returns void therefore data will be undefined.

Also, your redux action doesn't return the user so you can't chain from that either.

To access the user data, you need to return it from sendRequest()...

const sendRequest = async (type = "") => {
  try {
    const { data } = await axios.post(`/user/${type}`, { ...inputs });
    console.log("sendRequest", type, data);
    return data;
  } catch (err) {
    console.error("sendRequest", type, err.toJSON());
    throw new Error(`sendRequest(${type}) failed`);
  }
};

After that, all you really need is this...

sendRequest("...")
  .then((data) => {
    dispatch(authActions.login());
    localStorage.setItem('userId', data.user._id);
    navigate("/posts");
  });

Since you're using redux, I would highly recommend moving the localStorage part out of your component and into your store as a side-effect.

  • Related