简体   繁体   中英

Redux does not work now that I am using hooks and functional component?

I have been learning more about reactjs hooks for creating functional components as my knowledge lacked a lot in that area. I am using redux and I can't seem to get my actions to work properly in my functional component. My actions seem to never get called due to a console.log I set in them, therefore an array of data, listings, is always empty, but no errors are ever thrown. code is below.

here is the profile component:

import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Redirect, Link as RouterLink } from 'react-router-dom';
import { getUserListings } from '../../actions/listings';
import { getUserInfo } from '../../actions/users';
//material ui
import {
  Container,
  Typography,
  withStyles,
  Grid,
  Paper,
  Button,
  Link,
} from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import listings from '../../reducers/listings';

//antd
import { List, Avatar, Button as antButton, Skeleton, Row, Col } from 'antd';
import 'antd/dist/antd.css';

const useStyles = makeStyles({
  imgBox: {
    backgroundColor: 'white',
    height: '300px',
    marginTop: '30px',
    width: '400px',
    marginRight: '10px',
  },
  userBox: {
    backgroundColor: 'white',
    height: '300px',
    width: '700px',
    marginTop: '30px',
  },
  dashBox: {
    backgroundColor: 'white',
    height: '650px',
    width: '1110px',
    marginTop: '30px',
  },
});

const Profile = () => {
  const [loading, setLoading] = useState(false);
  const isAuth = useSelector((state) => state.users.isAuth); //using hook to pull state out from store
  const classes = useStyles();

  useEffect(() => {
    setLoading(true);
    getUserInfo();
    getUserListings();
  }, []);

  const listings = useSelector((state) => state.listings.listings);
  const user = useSelector((state) => state.users.user);

  if (!isAuth) {
    return <Redirect to={'/login'}></Redirect>;
  }

  return (
    <>
      <Row justify='center'>
        <Col>
          <Container className={classes.imgBox}></Container>
        </Col>
        <Col>
          <Container className={classes.userBox}></Container>
        </Col>
      </Row>

      <Row justify='center'>
        <Col>
          <Container className={classes.dashBox}>
            {listings.map((listing) => (
              <h3>{listing.title}</h3>
            ))}
          </Container>
        </Col>
      </Row>
    </>
  );
};

export default Profile;

here are the actions:

export const getUserListings = () => (dispatch) => {
  axiosInstance.get('/listings/userlistings').then((res) => {
    console.log('made it'); //never makes it here
    dispatch({
      type: GET_LISTINGS,
      payload: res.data,
    });
  });
};

export const getUserInfo = () => (dispatch) => {
  axiosInstance
    .get('/auth/getuserinfo')
    .then((res) => {
      dispatch({
        type: GET_USER_INFO,
        payload: res.data,
      });
    })
    .catch((err) => {
      console.log(err); //need to dispatch an error message here
    });
};

here are the reducers:

import {
  GET_LISTINGS,
  GET_LISTING,
  CREATE_LISTING,
  CLEAR_LISTINGS,
} from '../actions/types';

const initialState = {
  listings: [],
  isLoading: true, //ignore this for now never use it
};

export default function (state = initialState, action) {
  switch (action.type) {
    case GET_LISTINGS:
      return {
        ...state,
        listings: action.payload,
        isLoading: false,
      };
    case GET_LISTING:
      return {
        ...state,
        listings: action.payload,
        isLoading: false,
      };
    case CREATE_LISTING:
      return {
        ...state,
        listings: [...state.listings, action.payload],
      };
    case CLEAR_LISTINGS:
      return {
        ...state,
        listings: [],
      };
    default:
      return state;
  }
}

import {
  LOGIN_SUCCESS,
  REGISTER_SUCCESS,
  REGISTER_FAIL,
  LOGIN_FAIL,
  LOGOUT_SUCCESS,
  GET_USER_INFO,
} from '../actions/types';

const initialState = {
  isAuth: localStorage.getItem('isAuth'),
  user: {},
};

export default function (state = initialState, action) {
  switch (action.type) {
    case LOGIN_SUCCESS:
    case REGISTER_SUCCESS:
      const access = action.payload.accessToken;
      const refresh = action.payload.refreshToken;
      localStorage.setItem('accessToken', access);
      localStorage.setItem('refreshToken', refresh);
      localStorage.setItem('isAuth', true);
      return {
        ...state,
        isAuth: true,
      };
    case GET_USER_INFO:
      return {
        ...state,
        user: action.payload,
      };
    case LOGIN_FAIL:
    case LOGOUT_SUCCESS:
    case REGISTER_FAIL:
      localStorage.removeItem('accessToken');
      localStorage.removeItem('refreshToken');
      localStorage.removeItem('isAuth');
      return {
        ...state,
        user: {},
        isAuth: false,
      };
    default:
      return state;
  }
}

I get no errors, idk if i am calling the actions wrong or if I have my state all messed up. Fairly new to reactjs!!

You need to dispatch your actions for it to work seemlessly with redux, you can makeuse of useDispatch. As of now, you are just calling your actions and they only return the nested function. You need to update your code like

const dispatch = useDispatch();

  useEffect(() => {
    setLoading(true);
    dispatch(getUserInfo());
    dispatch(getUserListings());
  }, []);

When you do

    getUserInfo();
    getUserListings();

All you do is to create functions.

What you should do is to change you actions in something like:

export const getUserInfo = (dispatch) => {
  axiosInstance
    .get('/auth/getuserinfo')
    .then((res) => {
      dispatch({
        type: GET_USER_INFO,
        payload: res.data,
      });
    })
    .catch((err) => {
      console.log(err); //need to dispatch an error message here
    });
};

And then in your component

  const dispatch = useDispatch()
  useEffect(() => {
    setLoading(true);
    getUserInfo(dispatch);
    getUserListings(dispatch);
  }, []);

Note that the way you make your api calls should work but it is often preferred to separate asynchronous calls with some dedicated middlewares like redux-thunk

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM