Legend123
Legend123

Reputation: 378

ComponentWillReceiveProps Called Once With Multiple Sync Dispatches but Called Multiple Times With Async Dispatches?

index.js

class App extends Component {
    onClick = () => {
        this.props.update()
    }

    componentWillReceiveProps() {
        console.log('componentWillReceiveProps')
    }

    render() {
        return (
            <React.Fragment>
                <h1>{this.props.foo.foo}</h1>
                <button onClick={this.onClick}>Click Me!</button>
            </React.Fragment>
        );
    }
}

const action = dispatch => {
    dispatch({ type: 'foo', foo: 'first' })
    dispatch({ type: 'foo', foo: 'second' })
}

const mapStateToProps = ({ foo }) => ({ foo })

const mapDispatchToProps = dispatch => ({
    update: () => action(dispatch)
})

const ReduxApp = connect(mapStateToProps, mapDispatchToProps)(App);

render(
    <Provider store={store}>
        <ReduxApp/>
    </Provider>,
    document.getElementById('root')
)

redux.js

const foo = (state = {}, { type, foo }) => {
    if (type === 'foo') {
        return { foo }
    } else {
        return state
    }
}

const reducer = combineReducers({ foo })

const store = { foo: '' }

export default createStore(reducer, store, applyMiddleware(thunk))

I know that componentWillReceiveProps is deprecated but we are using an old version of react and our code relies on this method.

We ran into a really weird problem earlier where, with the above code, componentWillReceiveProps only gets called once, however if we change this line in index.js:

dispatch({ type: 'foo', foo: 'second' })

to this:

setTimeout(() => dispatch({ type: 'foo', foo: 'second' }), 1000)

then componentWillReceiveProps gets called twice. Why? How come dispatching 2 actions side by side causes this method to get called once but setting a timer calls it twice?

Upvotes: 0

Views: 91

Answers (1)

markerikson
markerikson

Reputation: 67489

Yes, this is because React batches updates if they are caused within a React event handler. Dispatching Redux actions ultimately results in calls to setState(). So, in the first case, both dispatched actions result in a single React re-render. In the second case, it results in two React re-renders.

Upvotes: 1

Related Questions