React-redux: connect obscures wrapped component's API

Created on 9 May 2016  Â·  6Comments  Â·  Source: reduxjs/react-redux

Hello,

We have a generic container component that calls sub-component's api methods. Wrapping our sub-components with connect obscures the sub-component's api, and therefore the container can't call its functions.
Using getWrappedInstance() isn't a good option as the container component is unaware of redux, and we want it to stay that way.
A good solution could be that the connect component will proxy to methods in the wrapped components, in case it doesn't implement them itself.

All 6 comments

Hi! This has been suggested before in #165 but we are unlikely to implement this, as there are way too many edge cases.

Putting imperative methods on a component is an escape hatch and is not idiomatic React code. If this is very important to you, you can write a custom connect() wrapper that also creates proxies for the instance method on the returned class. However we won’t add this feature to this library because the use case for imperative methods is rare, the risk of name clashes and weird issues resulting from them are high, and this is better addressed manually in the projects that need that so you have full control over how proxying happens.

Cheers!

@gaearon First of all thank for the impressively quick response (and overall great work).
Sorry I missed #165.

IMHO saying pure imperative methods is not idiomatic React is incorrect. A way of communicating with components through exposing a component function is part of the React docs:
https://facebook.github.io/react/tips/expose-component-functions.html

It even states at the end, that passing props for animations might get messy, or in other words, there are some situations a component interface is a better solution.

In our case, we have a generic wizard component, and each step in the wizard is a react component, that must implement a certain interface in order for it to work in the wizard.

A way of communicating with components through exposing a component function is part of the React docs:

Yeah, but it is explicitly listed as “uncommon”. I understand your use case but it’s rare enough that I would rather not bake it into the lib and have to support all the edge cases that come out of it (e.g. someone can define a handleChange method but it already exists on connect()ed component). If you’d like this to exist, please implement it on top of connect() manually.

In our case, we have a generic wizard component, and each step in the wizard is a react component, that must implement a certain interface in order for it to work in the wizard.

Unless you’re specifically managing “one-off” things like kicking an animation or focusing a text field, it is often possible to achieve the same with props. For example, components can cause imperative side effects in componentWillReceiveProps if the props changed. It’s hard to suggest more without a simple example.

Ok I understand your point.

(e.g. someone can define a handleChange method but it already exists on connect()ed component)

Just as a side note, you could only fallback to the component's interface in case the function isn't implemented in the _connect_ component, or throw an exception if a "reserved" function name is used.

Just as a side note, you could only fallback to the component's interface in case the function isn't implemented in the connect component, or throw an exception if a "reserved" function name is used.

This would make any internal change in connect() a potential breaking change because adding, removing, or renaming methods may cause methods with the same name to suddenly stop working in your app. This is a huge liability I’m not willing to take. It would make aggressive refactors like #373 much harder.

I wrote a small helper function that one can combine with connect() to expose functions and properties without overriding/replacing React/Redux methods. My solution can be found here:
https://stackoverflow.com/questions/42025434/unable-to-access-child-function-via-ref/48691310#48691310

One can call is a "complete anti-pattern" or "risky & hackish way of doing things" so use it wisely and at your own risk. :) It helped me a lot when I worked on my own ThreeJS-based scene graph library implementation. When writing a library I didn't want to make it dependent on Redux-specific behaviors and I needed to have exposed parent-children relations between components. It's a very special case so unless you have one too I wouldn't recommend using this. ;)

Was this page helpful?
0 / 5 - 0 ratings