Search code examples
reactjsreduxreact-hooksdispatchthunk

Dispatch form data to thunk results in 'breaking the rules of hooks' error


This is a simple task, but I'm doing something wrong and don't know how to do it right. Help is appreciated.

All I need to do is dispatch some form data to a thunk. The thunk has useSelector() in it, and I've built four or five slices similar with no problem. But this time I am 'breaking the rules of hooks', which I think I understand, but I don't know how to fix the problem and complete the task.

Here is some code

shippingInfo.js:

This function is called from the form's onSubmit (in a component named ShippingInfoDisplay.js). It dispatches 'saveAddress', which lives in the thunk:

   function handleSaveShippingInfo(e) {
        e.preventDefault();

        // many form fields taken from e.target and assigned to variables
   
        dispatch(saveAddress({ list of form variables })); // <<< this crashes the thunk. 'breaking the rules of hooks'
    }

Here are the first few lines of the 'saveAddress' thunk. It breaks when trying to get a token using a selector:

addressSlice.js:

export const saveAddress = createAsyncThunk (
    'addresses/saveAddress',
    async ( props, thunkAPI ) => {
        const { list of form variables  } = props;     
        let theApiUrl = API_BASE_URL + '/api/v1/address'
        authToken = useSelector(selectJwtToken) // <<< 'breaking rules of hooks' error

Most likely I am the source of the problem, since I don't yet understand hooks well enough. So far I understand that another piece is needed to fix the problem, but I don't know what that piece is. My best guess is that the dispatch to 'saveAddress' needs to be outside of the 'handleSaveShippingInfo(e)' function, but I don't know where to put it, or what else is needed to make it work.

In the meantime, I need to get this form submission done and have tried everything I can think of. Any guidance / help is greatly appreciated.

Thanks for your time and attention.


Solution

  • There are two ways to fix this issue:

    1. Passing jwt token to thunk action

    Component

    
     const  authToken = useSelector(selectJwtToken)
    
     function handleSaveShippingInfo(e) {
            e.preventDefault();
    
            // many form fields taken from e.target and assigned to variables
       
            dispatch(saveAddress({ ...list of form variables, authToken }));
        }
    

    thunk

    export const saveAddress = createAsyncThunk (
        'addresses/saveAddress',
        async ( props, thunkAPI ) => {
            const { list of form variables, authToken  } = props;     
            let theApiUrl = API_BASE_URL + '/api/v1/address'
    

    2. Get store state from thunkAPI

    export const saveAddress = createAsyncThunk (
        'addresses/saveAddress',
        async ( props, {getState} ) => {
            const { list of form variables  } = props;     
            let theApiUrl = API_BASE_URL + '/api/v1/address'
            const authToken = selectJwtToken(getState());