Sean D
Sean D

Reputation: 4292

Redux Thunk silently fails to update state

A child component has the following button code:

// SelectDonation.js
          <button
            onClick={(e) => {
              e.preventDefault();
              this.props.testThunk();
              console.log(store.getState());
            }}
          >Test thunks</button>

this.props.testThunk() does not update the state object. I connected Redux Thunk like so:

// reducer.js
import ReduxThunk from "redux-thunk";

const starting_state = {
  log_to_console : 0,
  donation_amount : 12,
  checkoutStep : 'selectDonation',
};

const reducer = (previous_state = starting_state, action) => {
  switch (action.type) {
    case 'thunkTest':
      return {
        ...previous_state,
        redux_thunk_test_var : action.payload
      };
    default:
      return previous_state;
  }
};

export default createStore(reducer, starting_state, applyMiddleware(ReduxThunk));

I expect a new state property redux_thunk_test_var to display in state but it does not onClick. I do see the state variables with initial states in the console though.

Am I not passing down the thunk correctly? Here is App.js

// App.js
          {this.props.checkoutStep === checkoutSteps.selectDonation &&
           <SelectDonation
            dispatch_set_donation_amount = {this.props.dispatch_set_donation_amount}
            dispatchChangeCheckoutStep={this.props.dispatchChangeCheckoutStep}
             {...this.props}
           />
          }         
          </Modal>
        </header>
      </div>
    );
  }
}

const map_state_to_props = (state) => {
  return {
    log_prop : state.log_to_console,
    donation_amount : state.donation_amount,
    checkoutStep : state.checkoutStep,
  }
};

const map_dispatch_to_props = (dispatch, own_props) => {
  return {
    dispatch_set_donation_amount : amount => dispatch(set_donation_amount(amount)),
    dispatchChangeCheckoutStep : newStep => dispatch(changeCheckoutStep(newStep)),
    dispatchUpdateStateData : (stateData, stateVariable) => (dispatch(updateStateData(stateData, stateVariable))),
    testThunk
  }
};

The action thunk:

// actions.js
export const testThunk = () => {
    const testDelay = setTimeout(() => 'Set Timeout done', 2000);
  return (dispatch) => {
    testDelay.then((data) => dispatch({
      type: 'thunkTest',
      payload: data })
    )
  }
};

Upvotes: 0

Views: 124

Answers (2)

user10334760
user10334760

Reputation:

conponentDidMount() {
  this.props.testThunk();
}

const map_dispatch_props = {
  testThunk
}


//action creator 

const fetch = (data) => ({
  type: 'thunkTest',
  payload: data
})


const fakeFetch = () => new Promise((resolve, reject) => setTimeout(() => resolve('Set Timeout done'), 2000));

export const testThunk = () => (dispatch) => fakeFetch.then(data => dispatch(fetch(data)))

Upvotes: 1

markerikson
markerikson

Reputation: 67469

You need to dispatch the result of the testThunk() action creator. Right now, you're just returning it, and not calling dispatch(testThunk()).

See this gist comparing syntaxes for dispatching to help understand the issue better.

The best way to fix this is to use the "object shorthand" form of mapDispatch. As part of that, I suggest changing the prop names to remove the word "dispatch", which lets you use the simpler ES6 object literal syntax:

const map_dispatch_to_props = {
    set_donation_amount,
    changeCheckoutStep,
    updateStateData,
    testThunk,
};

Upvotes: 1

Related Questions