Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connected component is rendered with stale state #1428

Closed
ckedar opened this issue Oct 16, 2019 · 2 comments
Closed

Connected component is rendered with stale state #1428

ckedar opened this issue Oct 16, 2019 · 2 comments

Comments

@ckedar
Copy link

ckedar commented Oct 16, 2019

Do you want to request a feature or report a bug?

Bug

What is the current behavior?

Under certain circumstances, a connected component is rendered with stale state.

One such case occurs when you have a stateful Child in a Container, both of them connected and child mutates both store and local state at the same time.

steps to reproduce

import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { connect, Provider } from "react-redux";

function counter(state = 0, action) {
  return action.type === "INCR" ? state + 1 : state;
}
const store = createStore(counter);

let Child = ({ state, dispatch }) => {
  console.log("Child.render. state =", state, " store.getState() =", store.getState());
  if (state !== store.getState()) {
    window.alert(`Got stale state ${state} !== ${store.getState()}`);
  }
  const [, setLocalState] = React.useState(0);
  const incrHandler = () => {
    setLocalState(localState => localState + 1);
    dispatch({ type: "INCR" });
  };
  return (
    <div>
      Child = {state}
      <button onClick={incrHandler}>Incr</button>
    </div>
  );
};
Child = connect(state => {
  console.log("Child. mapStateToProps");
  return { state };
})(Child);

let Container = ({ state }) => {
  console.log("Container.render. state =", state);
  return (
    <div>
      Container = {state}
      <Child />
    </div>
  );
};
Container = connect(state => ({ state }))(Container);

function App() {
  return (
    <Provider store={store}>
      <Container />
    </Provider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

https://codesandbox.io/s/suspicious-merkle-0kzcg

What is the expected behavior?

  • Component should never be rendered with stale state.
  • Also, on state and store mutation, the component should be rendered only once.

**Versions **

  "dependencies": {
    "react": "16.8.6",
    "react-dom": "16.8.6",
    "react-redux": "7.1.1",
    "redux": "4.0.4"
  },

@timdorr
Copy link
Member

timdorr commented Oct 16, 2019

Duplicate of #1298

@timdorr timdorr marked this as a duplicate of #1298 Oct 16, 2019
@timdorr timdorr closed this as completed Oct 16, 2019
@timdorr
Copy link
Member

timdorr commented Oct 16, 2019

BTW, the workaround for now is to set your component to non-pure mode:

Child = connect(state => {
  console.log("Child. mapStateToProps");
  return { state };
}, null, null, {pure: false})(Child);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants