Search code examples
reactjsreduxreact-reduxredux-thunk

redux hook fetch data from API with action in separate file


I'm learning redux hooks from library "react-redux" because I need to apply Redux also in the functional components of my project.

So far I don't understand how can be used the same project structure of the redux HOC with connect that I use for the class components.

Specifically I have a separate action file which invoke my API with axios:

FoosActions.js

import axios from "axios";
import {
  GET_FOO,
} from "./Types";

};

export const getFoo = () => async (dispatch) => {
  const res = await axios.get("/api/v1/foos");
  dispatch({
    type: GET_FOO,
    payload: res.data,
  });
};


FooList.js:

import { connect } from "react-redux";
import { getFoos } from "../../actions/FoosActions";

class FoosList extends Component {
  constructor() {
    super();

    this.state = {
      errors: {},
    };
  }
  componentDidMount() {
    this.props.getFoos();
  }
  
   render() {
    const { data } = this.props.foo;       
    return (

        <div className="container">
            <h2>foo data fetched from API endpoint  : </h2>
            <ul>
              {data.map((foo) => {
                return (
                    <li>
                      {foo.id} - {foo.name}
                    </li>
                );
              })}
              <ul>
            </div>
          </div>
        </div>
       
    );
  }
}

  const mapStateToProps = (state) => ({
    foo: state.foo,
    errors: state.errors,
  });

export default connect(mapStateToProps, { getFoos })(FooList);

FooReducer,js

import { GET_FOO} from "../actions/Types";

const initialState = {
  foos: [],

};

export default function (state = initialState, action) {
  switch (action.type) {
    case GET_FOO:
      return {
        ...state,
        foos: action.payload,
      };

Now instead in my Functional Component: FooListFC.js

import { useDispatch, useSelector } from "react-redux";
import { getFoo } from "../../actions/FoosActions";
const Mapping = (props) => {
    
  const [foo, setFoo] = useState([]);
  const dispatch = useDispatch();
  

  useEffect(() => {
    dispatch(getFoo());
    const fooRetrieved = useSelector((state) => state.foo);
    setFoo(fooRetrieved);
  }, []);
    
    return (
      <div className="container">
         <h2>foo data fetched from API endpoint  : </h2>
            <ul>
              {foo.map((foo) => {
                return (
                    <li>
                      {foo.id} - {foo.name}
                    </li>
                );
              })}
            </ul>
      </div>
    )

}

How can I reproduce the same behavior of fetching data from API in class component with actions in a different file and using redux hooks (my code in the functional component is not working) ?

Is it a bad practice having both approaches in the same project?


Solution

  • you are able to reproduce the same behaviour, in the function component you can use the selector only instead of both useSelector and useState:

    const Mapping = (props) => {
        
      const foo = useSelector((state) => state.foo);
      const dispatch = useDispatch();
      
      useEffect(() => {
        dispatch(getFoo());
      }, []);
    
      ...