0

I've already checked StackOverflow.com and also the entire internet for a similar question and didn't find any, so please ignore and do not give a negative reputation if you find one as I need reputation in this moment of my life!

My code works fine but I would like to know why calling an API request inside the Action-Creator file is not a good practice and what is the replacement for it?

MyComponent.jsx

const MyComponent = () => {
   dispatch = useDispatch();
   return <div>
      <button onClick={()=>{
          dispatch(getItems("?color=xxx&manufacturer=yyy"));
      }}></button>
   </div>
}

ActionCreator.js

const getItems = (queryString) => async (dispatch) => {
 try{
   dispatch({
      type: "FETCH_REQUEST",
   });

   // >>>>>> Here is the problem! <<<<<<
   const response = await fetch("https://subname.name.com/api/" + queryString);
   const data = await response.json();

   dispatch({
      type: "FETCH_SUCCESS",
      payload: data,
   });

 }catch(error){
    dispatch({
      type: "FETCH_FAILURE",
      payload: error,
   });
 }

}

Reducer.js

const INITIAL_STATE = {
    items: [],
    isLoading: false,
    error: "",
};

const reducer = (currentState, action) => {
    switch(action.type){
        case: "FETCH_REQUEST":
            return {
                ...currentState,
                isLoading: true,
        };

        case: "FETCH_SUCCESS":
            return {
                ...action.payload,
                isLoading: false,
        };

        case: "FETCH_FAILURE":
            return {
                items: [],
                error: "An error happend when fetching main data.",
        };
    }
}
Khaled Rakhisi
  • 317
  • 1
  • 4
  • 18
  • Commenting, as your question will probably be flagged as subjective (meta.stackexchange.com/questions/167516/…). Generally speaking, what is considered a bad practice is to have async logic embedded in your components. The idea is to decouple UI from async logic (see clean/hexagonal architecture). Now regarding what you can do, there are multiple options: native redux slices & thunks (https://redux.js.org/tutorials/fundamentals/part-8-modern-redux#writing-slices https://redux.js.org/usage/writing-logic-thunks), redux saga (https://redux-saga.js.org/) , rxjs (https://redux-observable.js.org)... – 7hibault Apr 04 '22 at 15:52
  • The official Redux Essentials tutorial shows multiple different ways that are considered best practice (chapters 5, 7 and 8). As your Redux style here is highly outdated anyways (modern Redux does not use switch..case reducers or ACTION_TYPES, among other things), I would highly recommend you to go through the [full official tutorial](https://redux.js.org/tutorials/essentials/part-1-overview-concepts) and also keep reading after your question has been answered there as you have clearly been following outdated sources. – phry Apr 04 '22 at 19:44

2 Answers2

0

I believe it is mainly based on what you're trying to do and what is the use case of the data.

for example, if you were trying to fetch user data to determine authentication or authorization, you should make the request as high as possible, whereas, if you are trying to fetch data that is only strictly needed on edge cases, using a button with an event listener should be fine.

Another option is using dispatch within useEffect or using a callback function dedicated to doing that.

I couldn't put it as a comment due to lack of reputation, but I've asked a more experienced developer and from what I could gather, the general response I got was - it's really depending on the data use case.

Nadav
  • 51
  • 6
0

You can Now use Redux ToolKit alongwith RTK query They also recommend to Use Typescript Nowadays

Using These Technologies will make your code more concise.

RTK query here


export const YourApi = createApi({
    reducerPath:"posts",
    baseQuery:fetchBaseQuery({
      baseUrl:"http://https://subname.name.com/api/"
    })
    endpoints:(builder) => ({
      getColor:builder.query<Your_Response_type, string|void> /** Cos you demand a string **/ {
       query:(input) => `${input}`
      }
    })
})

export const {useGetColorQuery} = YourApi 

then use it in your component using this hook


const { isLoading, isError, data, isSuccess } = useGetColorQuery(page)

return (
   <>
     {isLoading && 'Loading...'}
     {isError && 'Something went wrong'}
     {isSuccess && data}
   </>

)
  

You should read the Documentation

In this architechture redux toolkit does the same thing you did. There is nothing wrong with your architechture I also used to do it that way.