question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Impure connected component aren't updated when the store changes state

See original GitHub issue

From the docs:

[pure = true] (Boolean): If true, implements shouldComponentUpdate and shallowly compares the result of mergeProps, preventing unnecessary updates, assuming that the component is a “pure” component and does not rely on any input or state other than its props and the selected Redux store’s state. Defaults to true.

Given this, I would expect impure components to always be re-rendered whenever the store changes, as it cannot assume that some variable it depends on outside its props or the store hasn’t been mutated. However, this does not seem to be the case as this fiddle demonstrates:

const store = Redux.createStore(() => ({}));
let impureDependency = "Initial value";

class MyComponent extends React.Component {
    render() {
        return <div>{ impureDependency }</div>;
    }
}

const connect = ReactRedux.connect(() => ({}), null, null, { pure: false });
const MyConnectedComponent = connect(MyComponent);

ReactDOM.render(
    <ReactRedux.Provider store={store}>
        <MyConnectedComponent />
    </ReactRedux.Provider>,
    document.getElementById("container")
);

impureDependency = "Updated value";
store.dispatch({ type: "ACTION" });

The render method for MyComponent is dependent on variable impureDependency outside both its props and the Redux store, making it an impure component, and a connected version of the component, MyConnectedComponent, is subsequently created on line 11. This variable has its value changed from "Initial value" to "Updated value" on line 20. A dummy action is dispatched to the store on line 21 (causing the store state to change as store reducers will always return a new state), at which point we’d expect MyConnectedComponent to be re-rendered but the rendered text remains as "Initial value".

This is due to Connect.prototype.render() failing to check if a component is pure before determining whether re-rendering the component can be skipped or not. The solution is to add this check so that impure components always get re-rendered.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:10 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
DouglasLivingstonecommented, Jul 8, 2016

#416 should ultimately fix this as it uses shouldComponentUpdate to do all the checks.

Yes, I’ve tested #416 and it does fix this too.

seeing that invocationCount does not increase with the current fix.

Since merging props is always shallow, the shallow equality checks are sufficient to control whether a merge needs to happen or not. It is just that for impure objects, a shallow equality check isn’t sufficient to tell whether the wrapped component should re-render.

is this the expected behaviour?

I’d say yes, impure components should always return true from shouldComponentUpdate, since the props from the parent and the props from the store may have changed in a way that requires an update, even if they still match with a shallow equality comparison.

The docs say that the test for pure components is against mergedProps rather than against either ownProps or the props from the store, so the fix in #429 to have impure components ignore haveMergedPropsChanged seems correct.

1reaction
jimbollacommented, Jul 6, 2016

Yeah the test sounds valuable. I’ll try to pull it into my fork. I’m hoping the beta release happens sometime this week, but I can’t say when it might make it to production

Read more comments on GitHub >

github_iconTop Results From Across the Web

React component not updating when store state has changed
The state is 100% changing, however the component doesn't refresh. import React, { Component } from 'react' import { connect } from ...
Read more >
Connect | React Redux
This means that any time the store is updated, mapStateToProps will be called. The results of mapStateToProps must be a plain object, which...
Read more >
Redux: Generating Containers with connect() from React ...
Learn how to write mapStateToProps() and mapDispatchToProps() functions and use connect() from React Redux library to generate container components.
Read more >
Accessing the Store | React Redux
Accessing the Store. React Redux provides APIs that allow your components to dispatch actions and subscribe to data updates from the store.
Read more >
Kafka 3.3 Documentation
Edit the config/connect-standalone.properties file, add or change the ... Reverse iteration over state stores enabling more efficient most recent update ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found