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
Doesn't correctly support multiple props #270
Comments
Hi Eric, Thanks for providing a detailed example. What's the use case here for requiring prop conversion to be done independently? Is it possible to change how your components are connected to Redux to achieve the same result? e.g. instead of const Child1 = ({ a }) => { /*...*/ }
const Child2 = ({ b }) => { /*...*/ }
const Parent = (a, b) => {
<>
<Child1 a={a} />
<Child2 b={b} />
</>
};
// ...
export default connect(mapStateToProps)(withImmutablePropsToJs(Parent)); the following should achieve the desired result because of the built-in behaviour of const Child1 = connect(mapStateToPropsA)(withImmutablePropsToJs(({ a }) => { /*...*/ }))
const Child2 = connect(mapStateToPropsB)(withImmutablePropsToJs(({ b }) => { /*...*/ }))
const Parent = () => {
<>
<Child1 />
<Child2 />
</>
};
// ...
export default Parent; I have generally assumed re-render saving to be out of scope of this library because it already gets handled by react-redux, and as you mentioned it just increases memory footprint and adds complexity that is often an unnecessary optimization. |
Another option may be to preempt .toJS conversion for certain props that are causing you problems, e.g. const Child1 = ({ a }) => { /*...*/ }
const Child2 = ({ b }) => { /*...*/ }
const Parent = withImmutablePropsToJs((a, b) => {
<>
<Child1 a={a} />
<Child2 b={b} />
</>
});
// ...
const ParentWrapper = ({ a, b }) => {
const aToJs = useMemo(() => a.toJS(), [a])
<Parent a={aToJs} b={b} />
};
export default connect(mapStateToProps)(ParentWrapper); This is close to what you suggested above and might make sense as a supplemental component or separate API of this library. |
The use case is a big nested object living in the state: { project: { widgets: [...], pages: [...], metaData: {...}, layouts: [...]} // and the list goes on and so on. The problem is that most component will subscribe to the It's true that my state is maybe ill-designed and not flat enough, also I indeed need to connect more child components to the Redux state. This code dates from before the hook period so I lacked easy memoization in particular, and where redux was all the rage so we used it a lot to cache model objects that came from the backend as is. Yet I feel more confident in Immutable now that I am sure that all my JS object are guaranteed to change reference only when they change value, as the default behaviour, hence my initial proposal. To summarize my idea: Immutable, as used in most apps, is breaking Redux principle of immutability, not because it mutates values, but because it creates new object where there should be no new object, because of the mandatory final call to Thanks for the alternatives you propose, they are interesting! |
Nice okay that gives me a better idea of what you're working with, thanks. I'm going to mull this over a bit and it might make sense to add some APIs to help with your use case, since the official word is to use Immer with Redux now. So this library might be best suited to pivoting towards helping people migrate away from Immutable.js. Hopefully those alternatives help unblock you in the meantime. |
Yeah definitely, I think a link to this ticket in the Readme would probably be sufficient, given that only legacy apps are concerned. |
Description
If you have 2 immutable props A and B, a change in A will also recompute
.toJS()
for B.Steps to reproduce
Sharing the failing test and the fix:
The fix:
Fix (it's a naive 5 minute work so be careful! it might not work as expected!):
Also since it introduces memoization, there's a tradeoff, it's overkill if you don't have any performance issue.
It could maybe be exposed as another hoc in the same package, like "withMemoizedImmutablePropsToJS"
Edit: fixing initial computation, so state is initialized with the full values
The text was updated successfully, but these errors were encountered: