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

Cases where hooks don't currently provide a good answer vs HOC #14020

Closed
arieh opened this issue Oct 29, 2018 · 3 comments
Closed

Cases where hooks don't currently provide a good answer vs HOC #14020

arieh opened this issue Oct 29, 2018 · 3 comments

Comments

@arieh
Copy link

arieh commented Oct 29, 2018

(unsure if this is the right place, so trying it out)

I've noticed that the new React Hooks feature is aiming at providing an alternative composition pattern to HOC and render functions, but I believe that many of the use cases solved by HOC (at the framework level) cannot currently be addressed by the new hooks API.

Specifically, there is not way to incorporate React Hooks with React.memo. Unless I am incorrect, this means that any system that would like to implement optimisations based on external context, such as the react-redux connect function (that uses mapStateToProps to implement an efficient shouldComponentUpdate) will still need to rely on a HOC/render-prop to automate this optimisation.

The reason I am bringing this up is because one of the main benefits stated in the documentation is to reduce framework level use of HOC that "pollute" the tree, of which the react-redux connect HOC is probably the most prevalent use case.

Additionally redux (and useRedux) are specifically brought up as an exemplary use case, although with the current system it will cause large optimisation issues (since with no optimised shouldComponentUpdate, every "connected" component will re-render on every state change).
(Although this might fit into the documentation repo, this is a discussion / opinion and I do not feel it is a "mistake" that I should report, but rather a discussion on importance).

An example solution for this could be if there was a way to use contexts in React.memo (which unless I'm incorrect only have access to props and prevProps)

@danielkcz
Copy link

danielkcz commented Oct 29, 2018

If you check the docs for React.memo closely, you can see, there is a second argument which allows doing a similar optimization that is possible with shouldComponentUpdate. However, there are some whispers, that this is certainly not a final and you will be able to do it on a more granular level, especially with hook useState you should be able to decide if the component should rerender. I am not representing React team, so I cannot give you any more detail, but it's definitely under their radar.

Honestly, if you really want to optimize your renders, you can have a look at MobX. It already gives you much more granular control over what should rerender without any explicit checks in shouldComponentUpdate. Redux will never be that good, be sure of that.

https://twitter.com/mweststrate/status/1055532227939966976

@markerikson
Copy link
Contributor

markerikson commented Oct 30, 2018

Yes, I actually discussed this exact issue with Dan and Sophie at ReactConf.

To explain in a bit more detail, let's say I have the following setup:

// In some ancestor component. Ignore the inline object for this example.
<MyContext.Provider value={ {data: someLargeValue } } />

// Further down in the component
function SomeComponent() {
    const {data} = useContext(MyContext);

    const derivedData = deriveSomeData(data);

    // render output based on derived data
}

In this example, useContext(MyContext) will subscribe <SomeComponent> to any updated value given to MyContext.Provider. This is good, except for situations where you only care about the derived result, and might want to bail out of rendering unless that changes.

React-Redux is indeed a more concrete example. For version 6, we're going to be putting the entire Redux store state into context, but a given component would only want to re-render when the value extracted by its associated mapState function changes. A notional useRedux() hook would cause the component to always re-render when any part of the Redux store changed, not just when the derived value changes.

Dan and Sophie are aware of this, and want to add a way for functional components to bail out of rendering (ie, similar to shouldComponentUpdate(nextProps, nextState) returning false, or returning null from a setState() updater function). They said they wanted to have that in by the time hooks are finalized.

Once that is fixed, and 16.7 goes final, we would be able to ship a useRedux() hook that is equivalent to what connect does now. (We'll also then be able to ship an improved version of React-Redux v6 that is built with hooks internally, drastically simplifying the code - see reduxjs/react-redux#1065 for an idea of what that might look like implementation-wise.)

@aweary
Copy link
Contributor

aweary commented Oct 30, 2018

Please try and post all feedback/questions in the Hooks RFC so that the discussion doesn't get fragmented. Thanks!

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

No branches or pull requests

4 participants