0
const initialState = {

       user: [],
       isLoading: false,
       error: false
}

export const registerNewUser = createAsyncThunk('register/registerNewUser', 
    async({ rejectWithValue }) => {

    try {

    const resp = await axios.post('http://localhost:4000/register')
    return resp.data
      } catch (error) {
    return rejectWithValue(error.response.data)       
}

})

This is my register slice

const registerSlice = createSlice({

    name: 'user',
    initialState,
    reducers: {
      newUser: {
        reducer(state, action) {
      state.user = action.payload
     }
    }
},

 extraReducers(builder) {

    builder    

    .addCase(registerNewUser.pending, (state) => {
       state.isLoading = true;

})    

    .addCase(registerNewUser.fulfilled, (state, action) => {
      console.log(action);
      state.isLoading = false;
      state.error = false;
      state.user = action.payload
      console.log(action.payload);

})

    .addCase(registerNewUser.rejected, (state) => {
     state.isLoading = false;
     state.error = true;

})

    }

})

This is my function

const Home = () => {

    const dispatch = useDispatch()

    const navigate = useNavigate()
  
const errRef = useRef()

    const [name, setName] = useState('')
    const [username, setUsername] = useState('')
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const [id, setId] = useState(1)
    const [errMsg, setErrMsg] = useState('')

 useEffect(() => {

        setErrMsg('')

    }, [name, username, email, password])
    
const signupBtn = (e) => {

    e.preventDefault()

    try {
        dispatch(registerNewUser(newUser));
    
        if(name && username && email && password)
        navigate('/login')
    } catch (error) {
        console.log(error);
    }

And this is my store

import { configureStore } from '@reduxjs/toolkit'
import usersReducer from '../features/usersSlice'
import registerReducer from '../features/registerSlice'

export const store = configureStore({

    reducer: {

        users: usersReducer,
        register: registerReducer
    }
})
markerikson
  • 63,178
  • 10
  • 141
  • 157

1 Answers1

0

Two problems with the registerNewUser action creator:

  1. the arg parameter is missing from the argument list of the payload callback function, and
  2. the fulfillWithValue utility function is not being used to return (fulfill) a value from the action creator.

The signature of createAsyncThunk is: createAsyncThunk( <action_type_string>, <payload_callback_function>[, <options_object>] ).

The payload callback function has this signature: payload_callback_function( <arg>, <thunkAPI> ). <arg> is the value (most likely an object) passed to the payload callback function when calling the action creator. For example:

registerNewUser( newUser ); // where <arg> = `newUser`.

Your registerNewUser action creator payload callback function has the <thunkAPI> argument in the position where <arg> should be (i.e. the first argument in the argument list).

The Redux Toolkit docs say that:

fulfillWithValue is a utility function that you can return in your action creator to fulfill with a value...

Try updating registerNewUser to look something like this:

export const registerNewUser = createAsyncThunk('register/registerNewUser', 
  async( newUser, { fulfillWithValue, rejectWithValue }) => {

    // It isn't clear if you intended to use 'newUser' in this function or not.
    // But it is sent from your 'signupBtn' event handler function when
    // dispatch(registerNewUser(newUser)) is called.
    try {
      const resp = await axios.post('http://localhost:4000/register')
      return fulfillWithValue(resp.data)
    } catch (error) {
      return rejectWithValue(error.response.data)     
    }
  }
kofeigen
  • 1,331
  • 4
  • 8
  • Thank you very much. Really appreciate. Would try that out. – oluwatrillions Aug 23 '22 at 00:04
  • is it necessary to use `fulfillWithValue`, can't we return directly? When do we need to use it? – Yogendra Feb 15 '23 at 05:28
  • @Yogendra No, it is not necessary. Yes, you can return directly. The [documentation](https://redux-toolkit.js.org/api/createAsyncThunk#payloadcreator) says: The payloadCreator _should return a promise containing the result of some asynchronous logic. It may also return a value synchronously._ You can return a promise that resolves directly without using `fulfillWithValue`. It (and `rejectWithValue`) is helpful if you want to use the meta data (default data and optionally your own) passed to the reducers via the _action.meta_ property. See the documentation for details about _action.meta_. – kofeigen Feb 18 '23 at 19:36