1
votes

I'm trying to get redux working in my application, and I'm having trouble with state changes being passed to connected components. The mapStateToProps function is only being called on initialization and never again.

I've read through the Troubleshooting page and countless posts on forums and github issues. I've 100% ensured that I am not mutating state. I've applied middleware that compares state before and after an action is dispatched to help verify that at least there's a new reference.

Here's the basic middleware for ensuring that dispatching an action creates a new store reference

//Store Maker code to apply middleware
const logger = (store) => (next) => (action) => {

    var old_state = store.getState()

    var result = next(action)

    var new_state = store.getState()

    console.log("ENSURE FALSE", new_state === old_state)

    return result
}

export default () => {
    return applyMiddleware(logger)(createStore)(reducers)
}

Here's a snapshot of where I create the store and give it to a child component

//Parent Component code
const store = StoreMaker()

const unsubscribe = store.subscribe(() => {
    console.log("State Changed", store.getState())
})

...

class Plugin extends React.Component{

    ...

    render(){
        return (
            <Provider store={store}>
                <ChildComponent {...this.props} />
            </Provider>
        )
    }
}

Here is the most basic and pointless reducer I'm just using as I try to get this to work

//Reducer code
export default (state={}, action) => {
    if(action.type === "init"){
        return {
            ...state,
            test: 1
        }
    }
    else{
        return {
            ...state,
            test: 2
        }
    }
}

And finally, here's the child component

//Child Component code
class ChildComponent extends React.Component{
    constructor(props){
        super(props)
    }

    ...

    render(){
        return (
            this.props.test
        )
    }
}

const mapStateToProps = (state) => {
    console.log("Mapping state to props")
    return state
}

export default connect(mapStateToProps)(ChildComponent)

It is my understanding that the connect function from react-redux subscribes to the store and updates the connected component's props when there is a change via mapStateToProps. However, when there is a state change in my store, mapStateToProps is not called, and the connected component's props don't change. But the subscribe that I manually coded in the parent component just to log the state does fire, which makes me confused as to why mapStateToProps wasn't called.

I can't figure out what's going wrong, and I'm mirroring working examples almost identically. It'd be great if I could get some help.

Even just an idea of how to go about debugging would be really appreciated. I'm trying to use the Chrome Dev Tools to set a breakpoint in the react-redux code that subscribes to state changes and calls mapStateToProps, but I'm having trouble understanding what's going on in the source code. I'm trying to pinpoint where my code is failing to communicate the state change to my connected component.

2

2 Answers

1
votes

I wonder if it's that JavaScript primitives have problematic change detection (meaning it could be a JavaScript limitation, not a React/Redux one). Can you modify your example so instead of your state is a numeric primitive, it's a JavaScript object with that numeric primitive as a property? For example:

Change state from state = 0 to state = { value: 0 }

Let me know if that fixes it.

1
votes

If anyone else is wondering, the code above does actually work.

I was trying it with [email protected], [email protected], and [email protected].

Without changing any of the code, my problem was actually solved by switching to [email protected] (keeping [email protected] and [email protected]).

Not sure why this fixed it, but it did. Just writing this in case others have similar problems.