Maciej Kuta
Maciej Kuta

Reputation: 79

Problems with createAsyncThunk

I have just completed Learn Redux on Codecademy and want to that knowledge in practice. But I have an error. When I create extraReducers for updating the state to actual promise status it does not add information.

getUserSlice.js

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { fetchUserInfo } from '../../api';

export const loadUser = createAsyncThunk("getUser/loadUser",
    async (arg, thunkAPI) => {
        return await fetchUserInfo();
        
    }
});
const sliceOptions = {
  name: 'getUser',
  initialState: {
    info: [],
    isLoading: false,
    hasError: false,
  },
  reducers: {},
   extraReducers: (builder) => {
        builder
            .addCase(loadUser.pending, (state) => {
            state.isLoading = true;
            state.hasError = false;
            })
            .addCase(loadUser.fulfilled, (state, action) => {
            state.info.push(action.payload)
            
            state.isLoading = false;
            state.hasError = false;
            })
            .addCase(loadUser.rejected, (state, action) => {
            state.isLoading = false;
            state.hasError = true;
            })
    },
};

export const getUserSlice = createSlice(sliceOptions);
console.log(getUserSlice);

export const selectUserInfo = (state) => {
  console.log(state);
  return state;
};

export default getUserSlice.reducer;

api.js

export const fetchUserInfo = async () => {
   const user = await fetch('http://localhost:5000/api/user');
   const json = user.json();

   return json;
}

App.js

import React from 'react';
import './App.css';

import {Container} from 'react-bootstrap';
import Achievement from './components/Achievement/Achievement';
import { useSelector } from 'react-redux';
import { selectUserInfo } from './features/getUser/getUserSlice';



const colors = ['#010626','#4d6396', '#5d1a87', '#5d1a87', '#5d1a87'];

function App() {
 
   
  let color= colors[0];
  const user = useSelector(selectUserInfo)
  function changeColor() {
    const newColor = `rgb(${Math.round(Math.random() *256)}, ${Math.round(Math.random() *256)}, ${Math.round(Math.random() *256)})`;
    
    color = newColor;
  }
  
    return (
      <div className="App" style={{ background: color }}>
          <Container>
            <h1 id="whoAmI">
              Witaj na moim portfolio
              {user}
            </h1>
            <button onClick={changeColor}>
              Zmień kolor tła
            </button>
            <div className="col-lg-4 col-md-6 col-sm-12">
              <Achievement title="Ukończenie The Web Developer Bootcamp" picture="https://res.cloudinary.com/syberiancats/image/upload/v1630317595/k9g0nox2fyexxawg8whu.jpg" />
            </div>
          </Container>
         
         
      </div>
    );
  

  
  
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import reportWebVitals from './reportWebVitals';
import { store } from './store';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);


reportWebVitals();

store.js

import { configureStore } from "@reduxjs/toolkit";
import getUserReducer from "./features/getUser/getUserSlice";

export const store = configureStore({
    reducer: {
        getUser: getUserReducer
    }
})

Console.log of getUserSlice and state in the selector

console log (getUserSlice and second state)

Upvotes: 2

Views: 2087

Answers (2)

alansaldivar
alansaldivar

Reputation: 51

You can implicitly return and bypass the Promise result. Something like:

 (arg, thunkAPI) => fetchUserInfo();
        

However, I would take the "by-the-book" way:

export const loadUser = createAsyncThunk("getUser/loadUser",
    async (arg, tunkApi) => {
        try {
           const response = await fetchUserInfo();
           return response;
        } catch (e) {
          return thunkApi.rejectWithValue(e)
        }
    }
});

Upvotes: 0

Erwin Ramadhan
Erwin Ramadhan

Reputation: 402

Maybe you can use (builder) => {} function in extraReducer and you edit your loadUser because your Api.js already return json like code below:

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { fetchUserInfo } from '../../api';

export const loadUser = createAsyncThunk('getUser/loadUser', async (arg, thunkAPI) => {
  return await fetchUserInfo();
});
const sliceOptions = {
  name: 'getUser',
  initialState: {
    info: [],
    isLoading: false,
    hasError: false,
  },
  reducers: {},
  extraReducers: (builder) => {
  builder
    .addCase(loadUser.pending, (state) => {
     state.isLoading = true;
     state.hasError = false;
    })
    .addCase(loadUser.fulfilled, (state, action) => {
     state.info.push(action.payload)
     
     state.isLoading = false;
     state.hasError = false;
    })
    .addCase(loadUser.rejected, (state, action) => {
     state.isLoading = false;
     state.hasError = true;
    })
  },
};

export const getUserSlice = createSlice(sliceOptions);
console.log(getUserSlice);

export const selectUserInfo = (state) => {
  console.log(state);
  return state;
};

export default getUserSlice.reducer;

and you maybe forgot to add await before fetch, you should edit your fetching data in api.js into this below:

export const fetchUserInfo = async () => {
   const user = await fetch('http://localhost:5000/api/user');
   const json = user.json();

   return json;
}

Upvotes: 0

Related Questions