Description
redux: 4.0.0
react-redux: 5.0.7
description: (updated to make more sense to ppl arriving late to the issue)
So here is the contrived example, hopefully it's simple enough.
Basically what happens is that connect when provided a store property will create a storeSubscription and propagate it as a prop downwards, which means that if we have two HoC's with custom store, one wrapping another, the second one will try to use the storeSubscription from the first one even though it's creating its own one too. This results in actions fired by the second HoC not propagating changes until an action on the first HoC happens.
I do know that this is not a common use-case and that the tool is actually intended to be used with Provider, where this behaviour does not happen because the storeSubscription does not get propagated as a prop downward, but due to the nature of the projects I'm working on I'm encountering this issue/non-issue. I already have a workaround which is to instead of returning the connect hoc directly, return a wrapper on top of the connect hoc which discards both storeSubscription input prop and output propagated props.
Mainly i'd like to know if it is a bug or if this is the intended behaviour of connect, and what's the reasoning behind it on the latter as it might make sense to work like that due to a design decision.
https://codesandbox.io/s/qlk98486n9
index.js
import React from "react";
import { render } from "react-dom";
import { compose, mapProps } from "recompose";
import createPlugin from "./createPlugin";
const { HoC: plugin1HoC, action: plugin1Action } = createPlugin(
"attributeFromHoC1"
);
const { HoC: plugin2HoC, action: plugin2Action } = createPlugin(
"attributeFromHoC2"
);
const NestedPluginsComponent = compose(plugin1HoC, plugin2HoC)(props => (
<div>
<h2>props: {Object.keys(props).join(", ")}</h2>
<div>attributeFromHoC1: {props.attributeFromHoC1}</div>
<button onClick={plugin1Action}>plugin1Action</button>
<div>attributeFromHoC2: {props.attributeFromHoC2}</div>
<button onClick={plugin2Action}>plugin2Action</button>
</div>
));
const App = () => (
<div>
<NestedPluginsComponent />
</div>
);
render(<App />, document.getElementById("root"));
createPlugin.jsx
import React from "react";
import { createStore } from "redux";
import { connect } from "react-redux";
import { compose, withProps } from "recompose";
export default function createPluginHoC(name) {
const store = createStore(
(s, a) =>
a.type === "randomize"
? { [name]: Math.floor(Math.random() * 100 + 1) }
: s,
{}
);
return {
HoC: compose(withProps({ store }), connect(s => s)),
action: () => store.dispatch({ type: "randomize" })
};
}
To give some context, I'm currently working on autonomous embedded apps and plugins with custom stores that are used across multiple apps.
Is this an expected behaviour? should this be documented in that case? should this props not be propagated? or should the storeSubscription prop be ignored when the store property is provided?
Cheers!