lowcrawler
lowcrawler

Reputation: 7549

Actions not dispatching

When I run an action creator to create my thunk, it does not run the dispatch functions.

For testing, I put a button in my root component's render method, my root component is connected thusly (removed extraneous things):

import { loadAndSetCurrentUser } from '../Actions/SedFF';
import { setSysMenuExpand, setNavMenuExpand, setLoginDialogVisibility } from '../Actions/UI';

render() {
    return (
        <button onClick={() => 
            loadAndSetCurrentUser("[email protected]")}>LASCU</button>
    )
}

const mapStateToProps = function (state) {
    return {
        UI: state.UI,
        sedff: state.SedFF,
    }
}

const mapDispatchToProps = {
    loadAndSetCurrentUser,
}


export default withStyles(styles, { withTheme: true })(withRouter(connect(mapStateToProps, mapDispatchToProps)(WebFF)));

My Actions Creators file looks like this:

export function loadAndSetCurrentUser(username) {
    console.log("LASCU: " + username);
    return (dispatch, getState) => {
        console.log("in dispatch");
        dispatch(this.requestingUserData(username)); 

        const user = getState().Users[username];
        if (user) {
            // if already in store, just change the current username  
            //FUTURE: check date against user mod date in database
            dispatch(setCurrentUsername(username));
            dispatch(userDataLoadComplete());
        } else {
            // user not in store, need to check database //TODO:
            fetch('https://jsonplaceholder.typicode.com/users?username=Bret')
                .then(response => response.json())
                // .then(json => delay(3000, json))
                .then(json=> dispatch(ingestUserData(json)))
                .then(() => dispatch(userDataLoadComplete()));
        }
    }
}

export function requestingUserData(username) {
    console.log("RUD");
    return { type: REQUESTING_USER_DATA, username };
}

export function setCurrentUsername(username) {
    return { type: SET_CURRENT_USERNAME, username }
}

export function ingestUserData(userData) {
    return (dispatch) =>
        {
            console.log("IUD");
            console.log(userData);
            dispatch({ type: SET_USER_DATA, userData })
        }
}

export function userDataLoadComplete() {
    return { type: USER_DATA_LOAD_COMPLETE };
}

And my reducers are bone-stock, looking like this:

export function SedFF(state = initialSedFFState, action) {
    let newState = _.cloneDeep(state);
    switch (action.type) {
        case SET_CURRENT_USERNAME:
            newState.currentUsername = action.username
            return newState;
        case LOAD_USER_DATA:
            //TODO: 
             return newState;
        case REQUESTING_USER_DATA:
            newState.isFetchingUserData = true;
            return newState;
        case RECEIVED_USER_DATA:
            //TODO:
            newState.isFetchingUserData = false;
            return newState
        case USER_DATA_LOAD_COMPLETE:
            //TODO:
            newState.isFetchingUserData = false;
            return newState

... etc, etc...

        default:
            return state
    }
}

When I hit the LASCU button, I get the following output: LASCU: [email protected] coming from my action creator (noted on the second line of the action creator file above). I do NOT get the in dispatch output on the 4th line of my action creator file. I do NOT get any actions firing.

I'm unsure why the dispatch is not firing.

I will note that on a different component (a sub-component), I can get it to fire the entire thing, but I'm unable to find any differences. The only real difference appear to be that I don't have the router in the export line: export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(SystemMenu));

For what it's worth, my thunk middleware is connected at the App.js (parent of my root component) like so:

const store = createStore(
    RootReducer, 
    initialState, 
    composeEnhancer(applyMiddleware(thunk))
);

class App extends React.Component {

    render() {
        return (
            <Provider store={store}>
                <CssBaseline />
                <BrowserRouter>
                    <WebFF />
                </BrowserRouter>
            </Provider>
        );
    }
}


export default withStyles(styles, { withTheme: true })(App);

Thoughts? Help?

Upvotes: 0

Views: 1215

Answers (2)

markerikson
markerikson

Reputation: 67469

Looking at the render method given in the question, the issue appears to be that you're calling the original imported function, not the bound function from props. In other words, changing to this.props.loadAndSetCurrentUser() should work correctly. Note that you shouldn't be importing the store directly into a component file.

For more details, please see the React-Redux usage guide docs page on "Dispatching Actions with mapDispatch".

Upvotes: 1

XCS
XCS

Reputation: 28137

You still have to dispatch the Thunk action, otherwise it will just return the action and not do anything with it.

render() {
    return (
        <button onClick={() => 
            store.dispatch(loadAndSetCurrentUser("[email protected]"))
        }>LASCU</button>
    )
}

So, basically what you were doing was similar to:

const action = function (username) { return function () { alert(username); }}
console.log(action('123')); // This will just log `function () { alert(username); }`, without actually running the alert()

So, even though you call action('123'), it will just return a function that still has to be called somehow. In the case of Thunks, the returned function has to be dispatched.

Upvotes: 0

Related Questions