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

New version of context #2

Merged
merged 4 commits into from Jan 25, 2018

Conversation

@acdlite
Member

acdlite commented Dec 6, 2017

(supersedes #1)

A proposal for a new version of context addressing existing limitations.

Rendered

Corresponding React PR: facebook/react#11818

TODO:

  • Implementation notes
  • High-priority version of context, for animations. (May submit this separately.)
  • Add snippet showing how the displayName transform would work (#2 (comment)).
  • Add section about using narrow context types for maximum performance

acdlite added some commits Dec 6, 2017

RFC: New version of context
A proposal for a new version of context addressing existing limitations.

@acdlite acdlite referenced this pull request Dec 6, 2017

Closed

RFC: New version of context #1

0 of 2 tasks complete
@jaredpalmer

This comment has been minimized.

jaredpalmer commented Dec 6, 2017

@mjackson compareValues is a good idea. What's the default comparison in RB? ===?

@acdlite

This comment has been minimized.

Member

acdlite commented Dec 6, 2017

@jaredpalmer What's the use case for compareValues? I don't see one except to make mutation easier, which we're specifically aiming to discourage.

@mjackson

This comment has been minimized.

Member

mjackson commented Dec 6, 2017

@jaredpalmer Yep. === is the default.

@acdlite There's a difference between discouraging mutability and making it impossible to use, IMO. Seems like exactly what defaultProps are for: by default we'd prefer you don't mutate stuff. But if you need to, just override compareValues. AFAICT immutability isn't actually enforced anywhere else in React. One use case is passing around location objects from the current history API, which is mutable.

@acdlite

This comment has been minimized.

Member

acdlite commented Dec 6, 2017

@mjackson Mutation is not impossible with this proposal, it's just slightly less convenient. You can mutate one level down, just not the outermost container. Same as setState API.

@jaredpalmer

This comment has been minimized.

jaredpalmer commented Dec 6, 2017

Just giving an escape hatch to fallback to. I can see why this should be discouraged. However, mutation did come up in Formik the other day where I wanted to alter something within context if a certain declarative component existed in the subtree.

Edit: Ahh I see now that you can mutate one level down

@acdlite

This comment has been minimized.

Member

acdlite commented Dec 6, 2017

@mjackson

AFAICT immutability isn't actually enforced anywhere else in React.

Historically we have tried to be as forgiving of mutation as possible. When we introduce async rendering (this proposal is designed with async in mind), we may need to be a bit more restrictive.

However, there are cases where React already privileges immutability. setState is one. Another is that we bail out on React elements if the props objects are strictly equal (===). Often that isn't the case, because props objects are created in the render method as part of JSX / React.createElement. But it is the case for components that render this.props.children. If the component re-renders, but the parent didn't, the child elements will bail out on the unchanged props.

# How we teach this
This would be our first API that uses render props. They are an increasingly

This comment has been minimized.

@ljharb

ljharb Dec 6, 2017

"render props" and "function children" are different; no matter how they're implemented, children aren't just a normal prop - they're special (the third argument to createElement wins over a "children" prop, for example).

Please don't encourage function children.

This comment has been minimized.

@paularmstrong

paularmstrong Dec 6, 2017

Please don't encourage function children.

@ljharb Can you explain why this shouldn't be encouraged?

This comment has been minimized.

@pshrmn

pshrmn Dec 6, 2017

@paularmstrong One argument would be that children is almost always used as an implicit prop, but children as a function encourages using children as an explicit prop, which will lead to a bugs when someone attempts to use both at the same time.

<Thing children={firstFn}>
  woops
</Thing>
React.createElement(Thing, { children: firstFn}, 'woops')
{
  type: Thing,
  props: { children: 'woops' },
  ...
}

Yes, that can already happen, but I've never seen anyone write something like this:

<Thing
  children={
    <Well>
      <This is='awkward' />
    </Well>
  }
>
  ...
</Thing>

This comment has been minimized.

@kentcdodds

kentcdodds Dec 7, 2017

FWIW, @ryanflorence convinced me that it's easier to teach people a render prop accepts a function than it is to teach folks that the children prop can be a function. So in my teaching and open source I've been moving things over to render exclusively to hopefully make things more cohesive across the community while making it easier for people to pick up.

So, I'm in favor of using a prop called render personally.

This comment has been minimized.

@dmiller9911

dmiller9911 Dec 7, 2017

I completely agree with using render prop instead of children. In any instruction/demos I have given it is much easier for people to wrap their head around a prop called render over children being a function.

This comment has been minimized.

@gaearon

gaearon Dec 12, 2017

Member

That just depends on how you format this. You don’t have to indent it an extra time.

<MyComponent>
  {x => (
    <div>{x}</div>
  )}
</MyComponent>

That's how Prettier formats it too.

This comment has been minimized.

@bvaughn

bvaughn Dec 12, 2017

Collaborator

By default, Prettier formats both as 1-liners 😄

<div>
  <MyComponent>{x => <div>{x}</div>}</MyComponent>
  <MyComponent render={x => <div>{x}</div>} />
</div>;

This comment has been minimized.

@FezVrasta

FezVrasta Feb 2, 2018

Just my 2 cents, if we go with a render prop we may as well drop children all together, no reason to keep two props that serve the exact same purpose...

Just to say, please keep children, if one prefers the explicit prop approach, they can do:

<Foo children={x => x} />

If one does:

<Foo children={x => x}>y</Foo>

I'd first ask myself what am I trying to achieve, and then think

the inner content of a component is just treated as children, so I'm just defining children twice, where the latter will take precedence, like any other prop in React

This comment has been minimized.

@fbartho

fbartho Feb 2, 2018

I just want to support the part where @FezVrasta wrote "please keep children-as-func". :)

This comment has been minimized.

## Add displayName argument to createContext for better debugging
For warnings and React DevTools, it would help if providers and consumers
had a `displayName`. The question is whether it should be required. We could

This comment has been minimized.

@ljharb

ljharb Dec 6, 2017

If they have a function name, they don't need a displayName - perhaps making getComponentName(…) required, but not displayName specifically?

This comment has been minimized.

@gaearon

gaearon Dec 6, 2017

Member

My original point is that with this API (unlike existing one) we don’t know which context is missing to show a meaningful warning. Passing a name (explicitly or implicitly) to createContext would solve that.

This comment has been minimized.

@ljharb

ljharb Dec 6, 2017

Totally fair, I'm 100% fine with requiring a name - just not requiring displayName specifically, since normal function names should be more than sufficient.

This comment has been minimized.

@gaearon

gaearon Dec 6, 2017

Member

createContext() isn’t bound to any component or function in particular so it can’t read a .name from it. Therefore my proposal is to make it an argument (even if optional). I think that’s what displayName was referring to. For example:

const Theme = React.createContext('light', {
  displayName: 'Theme’
});

Sorry if I’m missing your point.

This comment has been minimized.

@acdlite

acdlite Dec 7, 2017

Member

Another option is

const Theme = React.createContext('light');
Theme.displayName = 'Theme';

This comment has been minimized.

@ljharb

ljharb Dec 8, 2017

@gaearon ah, I misunderstood. In that case, yes, I'd say requiring displayName makes perfect sense.

This comment has been minimized.

@Andarist

Andarist Dec 9, 2017

Static patterns like:

const Theme = React.createContext('light');
Theme.displayName = 'Theme';

can often prevent tree-shaking/dead code elimination. I'd advise not to recommend this officially, better to have an optional extra param for createContext + maybe auto add static displayName with babel plugin for the development purposes.

## Other
* Should the consumer use `children` as a render prop, or a named prop?

This comment has been minimized.

@ljharb

ljharb Dec 6, 2017

named prop, please. children are special, and should only be nodes.

This comment has been minimized.

@jaredpalmer

jaredpalmer Dec 6, 2017

+1 for render

This comment has been minimized.

@jamesplease

jamesplease Dec 7, 2017

children are special, and should only be nodes.

Would you mind elaborating on this a little more?

One thought I have is that a new prop could be considered as API bloat if children already functions exactly as it needs to. I'm not convinced one way or the other on this one, by the way; I'm just sharing one more thing worth considering.

This comment has been minimized.

@JNaftali

JNaftali Dec 7, 2017

The type signature for the children prop is pretty consistent across all built-in React components (that I can think of) and most components shipped with third party libraries - Component | SFC | string | etc. The two big exceptions that I've seen are components that don't support children at all and components that require a single child component (React Router's FooRouter components spring to mind).

In particular I think the distinction between (foo) => <DomElement /> vs ({foo}) => <DomElement /> and {renderProp} vs <FunctionalComponent /> is a fine one. I could see that getting confusing in particular if the render prop function isn't defined inline.

All that is why I prefer an explicit 'render' prop, anyway. My knowledge of the React ecosystem is not nearly as in-depth as many of yours' - are there lots of big exceptions that I'm not thinking of?

Edit to add: this is all a user's perspective, not a package author's. If you're still gonna try and discourage users from using the new Context API all of the above might be considered a plus.

This comment has been minimized.

@jamesplease

jamesplease Dec 7, 2017

That makes sense to me, @JNaftali . I’m now leaning more in favor of a separate prop as well.

This comment has been minimized.

@stryju

stryju Dec 8, 2017

You can always pass children as prop:

<Foo children={() => {...}} />

This comment has been minimized.

@jedwards1211

jedwards1211 Dec 10, 2017

@ljharb Components have always been free to do whatever they want with children. I would agree with you if React by design always passed through children unaltered, but there are so many library components out there that conditionally render children, render them inside wrappers (e.g. interactive rearrangeable grids), etc. that I think "children are special" is a dangerous argument that leads to restricting the power of React.

This comment has been minimized.

@jedwards1211

jedwards1211 Dec 10, 2017

also, saying that children should only be nodes because they are "special", or because the third argument to createElement wins over a "children" prop, are non-arguments. They don't really explain what if anything you consider cleaner, easier to read, easier to understand, less error prone, etc. about ensuring that children are only nodes.

This comment has been minimized.

@JNaftali

JNaftali Dec 10, 2017

I don't see how a convention could possibly 'restrict the power of React'. Conventions don't stop you from doing anything. They're just a tool to make it easier for other people to understand how to use the things you write. React's power is such that given any one of these APIs it'd be easy to implement any of the others that will remain true no matter which of these APIs get implemented.

This comment has been minimized.

@jedwards1211

jedwards1211 Dec 10, 2017

That's true, it's not clear to me if @ljharb is just advocating this as a convention or if he would be in favor of dropping support for function children from React.

As far as making things easier to understand...personally I find child functions more obvious than render functions in other props, but I guess I'm in the minority.

## Other
* Should the consumer use `children` as a render prop, or a named prop?
* How quickly should we deprecate and remove the existing context API?

This comment has been minimized.

@ljharb

ljharb Dec 6, 2017

very slowly. Separately, it must be possible to write a component that can work, simultaneously, on old React (with current context) and new React (with new context).

This comment has been minimized.

@acdlite

acdlite Dec 6, 2017

Member

That's a good point about libraries needing to support both APIs at the same time

This comment has been minimized.

@gaearon

gaearon Dec 7, 2017

Member

Implementation wise could we only leave the new implementation but polyfill the old API on top of it (with current broken semantics)?

This comment has been minimized.

@acdlite

acdlite Dec 7, 2017

Member

Ooh maybe! Should at least consider it.

This comment has been minimized.

@ljharb

ljharb Dec 7, 2017

As long as I can trivially author a package that can work in both, I consider this addressed :-)

@baptistemanson

This comment has been minimized.

baptistemanson commented Dec 6, 2017

We didn't use context that much and decided to use Redux instead.

To provide some inputs, I scanned one module. If it helps:

  • out of our 19 redux-connected components, we have 12 components that have only one value selected from the state, aka one selector. Mostly, isLogged, isLoading or isOnline. This proposal totally covers this case elegantly.
  • The remaining 7 components have an average of 4 selectors, to a max of 6. Reading the code, they all seem legitimate to me but we may have got it wrong: isLogged, isOnline, isLoading, getItemsPage, getTotalOfItems, getTheme.
    The new context still sounds laborious in that case.
@gaearon

This comment has been minimized.

Member

gaearon commented Dec 6, 2017

To be clear even if you use Redux, React Redux still uses context under the hood. The problem is it has to reimplement a tree-aware subscription mechanism. And that won’t work very well with React async mode. The proposal is both about making context friendlier for direct use and to make it better for libraries built on top (such as React Redux).

@milesj

This comment has been minimized.

milesj commented Dec 6, 2017

(Copied from previous PR)

I think a life-cycle hook in regards to context changes should be discussed. Relying on a child function for detecting this isn't exactly feasible for all situations. Perhaps another prop on the consumer?

<Consumer onChange={this.handleChange} />
@jlongster

This comment has been minimized.

Member

jlongster commented Dec 6, 2017

@milesj brings up a good point. It took me a bit to parse his question but I think he's getting at this: what if you need the context value in any of the lifecycle hooks?

The problem with a render prop API is it makes that very difficult; I've run into this problem with other render prop-based APIs as well. Take AutoSizer which gives you the width/height. I needed to do something special with the width to figure out if I should render something or not, and that logic needs to be re-run when something else changes in a lifecycle, so I need the width there. Hope that makes sense, I can't remember the details of the problem.

Is the suggested pattern to pull out all the lifecycle code that needs to depend on it into a sub-component, and pass the value down as a prop to it? I think that works but seems a bit ceremonious.

@acdlite

This comment has been minimized.

Member

acdlite commented Dec 6, 2017

@jlongster

Is the suggested pattern to pull out all the lifecycle code that needs to depend on it into a sub-component, and pass the value down as a prop to it? I think that works but seems a bit ceremonious.

Yes, this is the main problem with render prop APIs. I think this is mostly an educational challenge, though, because there's always the option to wrap it in an HOC:

function consume(Context) {
  return Component => {
    return function Consumer(props) {
      return (
        <Context.Consumer>
          {context => <Component context={context} {...props} />}
        </Context.Consumer>
      );
    }
  }
}
@acdlite

This comment has been minimized.

Member

acdlite commented Dec 6, 2017

Usually my objection to wrapping in an HOC, versus using an HOC from the start, is it requires two extra components instead of one. But in this case, we want the extra Consumer component because they're faster to scan for.

@jlongster

This comment has been minimized.

Member

jlongster commented Dec 6, 2017

Faster to scan in what case? Is that benefit enough to warrant a HOC in the default API?

(Thanks for explaining!)

@acdlite

This comment has been minimized.

Member

acdlite commented Dec 6, 2017

Faster to scan for Consumer components. By adding another node into our internal tree, with a special type that is distinct from class components, we can quickly skip over non-consumer nodes.

To be clear, we could still implement it this way with an HOC-first API. I was just rebutting my own devil's advocate point about adding extra nodes to the tree :D

EDIT: Realized I misread your question. Faster to scan for Consumer components when a provider changes. We don't do this every time there's a change, only on the first update. Then the result is cached. We may have to re-scan if the cache is cleared.

@acdlite

This comment has been minimized.

Member

acdlite commented Dec 6, 2017

I'm working on adding a high-level description of the implementation, will try to publish later today or tomorrow.

@oliviertassinari

This comment has been minimized.

oliviertassinari commented Dec 6, 2017

Will the new API support provider nesting like we can do it today? One use case example is nested theme.

@acdlite

This comment has been minimized.

Member

acdlite commented Dec 6, 2017

@oliviertassinari Yes

@milesj

This comment has been minimized.

milesj commented Dec 7, 2017

@jlongster That's half of the question. But basically, I think the new context would need to hit these points:

  • New life-cycle event(s) for when the context changes (componentWillReceiveContext)? Passing the context prop to a component, in which that component needs to componentWillReceiveProps, adds another layer of abstraction and feels very tedious/contrived. My rudimentary solution above was simply a prop handler for when the context changes, instead of a new life-cycle method.
  • Checking the context value in existing life-cycle events. Theoretically this can be achieved by accessing the context prop.
container. (Or even just alternate between two copies.) React will detect a new
object reference and trigger a change.
## Only one provider type per consumer

This comment has been minimized.

@kentcdodds

kentcdodds Dec 7, 2017

Someone will inevitably develop a component to do this composition automatically. I'm not worried about this drawback 👌

This comment has been minimized.

@sprjr

sprjr Dec 7, 2017

Agreed, and while I'm not super excited about the (below) suggested layering I'm certain that if one wasn't available I'd simply make one for use in apps to layer them together ala <ApplicationKitchenSinkConsumer> or something like that.

This comment has been minimized.

@baptistemanson

baptistemanson Dec 7, 2017

I agree with you about the tooling, it will happen because it is necessary.
Inspectors, stack trace and performance may be impacted by the layering though.

This comment has been minimized.

@kentcdodds

kentcdodds Dec 7, 2017

I honestly doubt this will happen all that often... 🤷‍♂️

This comment has been minimized.

@acdlite

acdlite Dec 7, 2017

Member

Also consider that we can change the DevTools to display this however we like

This comment has been minimized.

@baptistemanson

baptistemanson Dec 7, 2017

@acdlite Indeed! DevTools improvements for HOC/layering makes sense beyond this RFC I think.

@kentcdodds I grep'ed the code of our apps this afternoon to review the impact of this RFC. We only have about 25 developers working with React, so consider my feedback with a grain of salt - we do not have the same stats as Facebook has :).
Our login button render method changes when logged or not authenticated (login or logout), on the theme (color), on being connected to the network or offline (disabled) and on the language of the user.

Overall, 20% of our context dependent render methods read 2 or more "atomic global state variable". If I understood correctly, the RFC suggests that if we want to only use React with no 3rd party tool, we should use 1 Context Consumer for each Context Providers we want to "consume from" - it sounds inconvenient to me.
But we already tooled ourselves with Redux and the RFC doesn't degrade our Redux experience so if it solves problems for others, go!

What about your React applications?

This comment has been minimized.

@kentcdodds

kentcdodds Dec 7, 2017

Most applications don't use the context API directly in every component that needs it and instead use an abstraction of some kind (HOC, render prop, or something else) to access context. In this case, the impact of the APIs verbosity is pretty minimal and the benefits of the new API make it easily worth it.

# How we teach this
This would be our first API that uses render props. They are an increasingly

This comment has been minimized.

@kentcdodds

kentcdodds Dec 7, 2017

FWIW, @ryanflorence convinced me that it's easier to teach people a render prop accepts a function than it is to teach folks that the children prop can be a function. So in my teaching and open source I've been moving things over to render exclusively to hopefully make things more cohesive across the community while making it easier for people to pick up.

So, I'm in favor of using a prop called render personally.

This would be our first API that uses render props. They are an increasingly
popular pattern in third-party React libraries. However, there could be learning
curve for beginners.

This comment has been minimized.

@kentcdodds

kentcdodds Dec 7, 2017

Can't deny the learning curve. But to be fair, there's a learning curve (and arguably a steeper one) with the current context API. In addition, I think people will start to see render prop APIs before they have to start using context themselves. So it's unlikely that people will come to the context API before they've experienced a similar API with other libraries first.

This comment has been minimized.

@karlbright

karlbright Dec 7, 2017

Agreed with @kentcdodds, context has a learning curve. I think beginners coming across the proposed context API, making use of a render prop, will have a much easier time grokking what is happening, or where to start with it.

This comment has been minimized.

@brentmclark

brentmclark Dec 7, 2017

The bigger learning curve for the existing context API is trudging through myriad opinions about whether or not it's a good idea to use it, and, if so, how to use it safely.

This proposal being slightly more opinionated seems like it would result in a more gradual learning curve.

For warnings and React DevTools, it would help if providers and consumers
had a `displayName`. The question is whether it should be required. We could
make it optional, and use a Babel transform to add the name automatically. This

This comment has been minimized.

@kentcdodds

kentcdodds Dec 7, 2017

Could we make it required, but have the babel plugin add the displayName in the function call automatically? Best of both worlds?

const ThemeContext = React.createContext('light')

↓ ↓ ↓ babel plugin ↓ ↓ ↓

const ThemeContext = React.createContext('light', {
  displayName: 'ThemeContext',
})

This comment has been minimized.

@acdlite

acdlite Dec 7, 2017

Member

Yeah, that's what I was trying to communicate. Maybe I'll just copy your snippet :D

I was thinking the displayName property would be assigned to the context object directly, as with other component types:

const ThemeContext = React.createContext('light')

↓ ↓ ↓ babel plugin ↓ ↓ ↓

const ThemeContext = React.createContext('light');
ThemeContext.displayName = 'ThemeContext';

This comment has been minimized.

@kentcdodds

kentcdodds Dec 7, 2017

Sounds fine. I thought making it part of the createContext call would make it easier to log an error. I don't really care how it's implemented though 😅

This comment has been minimized.

@Andarist

Andarist Dec 9, 2017

If you want to make the plugin to output static property, please make it in such fashion

const ThemeContext = React.createContext('light');
if (process.env.NODE_ENV === 'development') {
  ThemeContext.displayName = 'ThemeContext';
}

Otherwise statics will prevent tree-shaking. This could be configurable with wrap option for the transform which would default to true

This comment has been minimized.

@gaearon

gaearon Dec 9, 2017

Member

Or, rather,

const ThemeContext = React.createContext('light');
if (process.env.NODE_ENV !== 'production') {
  ThemeContext.displayName = 'ThemeContext';
}

to match how we do other checks.

return (
// The Consumer uses a render prop API. Avoids conflicts in the
// props namespace.
<ThemeContext.Consumer>

This comment has been minimized.

@sprjr

sprjr Dec 7, 2017

I noticed a few of our internal apps started using redux in a way such that they do not connect leaf components but instead just rely on the store being accessible on this.context and they grab things from there directly. I'm not saying this is a recommended approach just that it is one I've seen taken.

Given that behavior (or other direct context access and not using a context -> props hoist component) what would be the migration story for apps wanting to update and needing to replace that with the new <ThemeContext.Consumer>?

I realize that's a bit of a loaded question, but it seems like it wouldn't necessarily be something that could be code shifted at all, I imagine.

This comment has been minimized.

@baptistemanson

baptistemanson Dec 7, 2017

Intuitively, the migration to using connect()+props instead of reading straight out of context would be my first investigation.
A grep like:

$grep -hr this\.context src/

should give you an idea of the amount of effort required for this direction. Hope that helps!

This comment has been minimized.

@karlbright

karlbright Dec 7, 2017

Discussion around how long existing API would hang around, and implementation for that can be found #2 (comment)

This comment has been minimized.

@acdlite

acdlite Dec 7, 2017

Member

If you give a static value (like store) to a context provider, consuming it in a child is basically free. So you can continue to use it for the this.context.store use case. The only difference is you'll have to use the render prop, instead of accessing it on the instance. Unfortunately this means there's no obvious way to codemod this, but it shouldn't be hard for a human to do the migration.

@suchipi

This comment has been minimized.

suchipi commented Dec 7, 2017

It might be nice for React to ship an "official" HOC for consuming Context in the lifecycle, so that it can be treated differently in React DevTools (different color or etc). It's already inconvenient to dig through a ton of layers of components when using context-based APIs; needing to add another layer to get context in lifecycle methods will exacerbate the issue.

static values is still supported.
Replacing subscription-based patterns in favor of context's built-in change
propgation may require a larger effort. However, as a first step, developers can

This comment has been minimized.

@jamesplease

jamesplease Dec 7, 2017

small typo: propagation

the previous context, and return true if they are different. The problem is
that, unlike props or state, we have no type information. The type of the
context object depends on the component's position in the React tree. You could
perform a shallow comparion of both objects, but that only works if we assume

This comment has been minimized.

@jamesplease

jamesplease Dec 7, 2017

small typo: comparison

(if you plan to do a spellcheck at some point, no worries; I can stop pointing these out. I'm just reading through this document and pointing them out as I find them. By the way, this is great so far! Thank you! ✌️ )

This comment has been minimized.

@acdlite

acdlite Dec 7, 2017

Member

Ha your spellchecks are appreciated :)

mjackson added a commit to ReactTraining/react-broadcast that referenced this pull request Jan 18, 2018

New API to match context RFC
This is an API overhaul to more closely match the API currently being
proposed in reactjs/rfcs#2

The main goals of this work are:

- Conform more closely to the upcoming context API, to make it easier
  for people to migrate off react-broadcast when that API eventually
  lands
- Remove reliance on context entirely, since eventually it'll be gone
- Remove ambiguity around "channel"s

The new API looks like:

    const { Broadcast, Subscriber } = createBroadcast(initialValue)

    <Broadcast value="anything-you-want-here">
      <Subscriber children={value => (
        // ...
      )} />
    </Broadcast>

Instead of providing pre-built <Broadcast> and <Subscriber> components,
we provide a createBroadcast function that may be used to create them.

See the README for further usage instructions.

@mpeyper mpeyper referenced this pull request Jan 22, 2018

Closed

How to use with reselect? #68

@giuseppeg giuseppeg referenced this pull request Jan 24, 2018

Closed

Async safe SSR #389

@acdlite acdlite merged commit b091fdb into reactjs:master Jan 25, 2018

@streamich

This comment has been minimized.

streamich commented Jan 25, 2018

This proposes an interface that can be done entirely in a 3rd party library. Then why include context in react at all?

import {Provider, Consumer} from 'react-context';

<Provider value={123}>
  <Consumer>{value => /* ... */}</Consumer>
</Provider>

React is already too big, better separate it in another lib, like you did with ReactDOM and PropTypes.

@TrySound

This comment has been minimized.

Contributor

TrySound commented Jan 25, 2018

@streamich This proposal can be implemented as 3rd party library only with current context implementation which is not lying in async rendering idea and will be removed in v17. There's still should be parent/child relationship.

@TrySound

This comment has been minimized.

Contributor

TrySound commented Jan 25, 2018

@streamich Also there is 3rd party polyfill create-react-context

@streamich

This comment has been minimized.

streamich commented Jan 25, 2018

@TrySound Can't you keep track parent/child relationship in a third party library as well?

@TrySound

This comment has been minimized.

Contributor

TrySound commented Jan 25, 2018

@streamich I can't. Can you?

@taion

This comment has been minimized.

Member

taion commented Jan 25, 2018

@acdlite

First off, great job on the implementation. It looks really nice, and I actually like it more than what's on this RFC – it fully addresses my concerns here.

However, the implemented API is moderately different from the API proposed here. Can you comment on the bearing this has on the way the RFC process is supposed to work?

There was no "final comment period" per https://github.com/reactjs/rfcs#what-the-process-is, and no mention was made of the changes to the implemented API here.

I have no problems with the end result, but the process here doesn't seem to have followed what was described.

@gaearon

This comment has been minimized.

Member

gaearon commented Jan 25, 2018

I think the plan was to land the change now so we can start testing it internally, but hold off the final API decision until the actual release. But yeah, this means RFC should’ve probably stayed open until we do that.

@taion

This comment has been minimized.

Member

taion commented Jan 25, 2018

Great. Shall we reopen then?

@taion

This comment has been minimized.

Member

taion commented Jan 25, 2018

Oops, never mind. Guess it’d have to be a new PR.

@gaearon

This comment has been minimized.

Member

gaearon commented Jan 25, 2018

I'll bring it up that we should do this for future RFCs (or amend the process description). I don't think it makes sense to introduce more bureaucracy now that it's already merged though.

@acdlite

This comment has been minimized.

Member

acdlite commented Jan 25, 2018

@taion In my mind, merged means "accepted" but not necessarily "completed." Thanks for the feedback! If you have other comments please open a PR against the existing document. I'm sure we'll get the hang of this process eventually :D

@ljharb

This comment has been minimized.

ljharb commented Jan 25, 2018

Internal testing can be done off an unmerged branch though, no?

@gaearon

This comment has been minimized.

Member

gaearon commented Jan 25, 2018

That's pretty hard with our continuous release model. We prefer to always land changes in master and hide them behind feature branches instead.

@taion

This comment has been minimized.

Member

taion commented Jan 25, 2018

I think @gaearon's point is right. We should have just left the PR open while the strawman implementation was around, then gone through the "final comment period" and all the rest before accepting the RFC and shipping the new code.

@mxstbr mxstbr referenced this pull request Jan 29, 2018

Closed

Switch to new context API #1459

@chadmorrow-fd chadmorrow-fd referenced this pull request Jan 31, 2018

Closed

Support contexts #3

mjackson added a commit to ReactTraining/react-broadcast that referenced this pull request Feb 1, 2018

New API to match context RFC
This is an API overhaul to more closely match the API currently being
proposed in reactjs/rfcs#2

The main goals of this work are:

- Conform more closely to the upcoming context API, to make it easier
  for people to migrate off react-broadcast when that API eventually
  lands
- Remove reliance on context entirely, since eventually it'll be gone
- Remove ambiguity around "channel"s

The new API looks like:

    const { Broadcast, Subscriber } = createBroadcast(initialValue)

    <Broadcast value="anything-you-want-here">
      <Subscriber children={value => (
        // ...
      )} />
    </Broadcast>

Instead of providing pre-built <Broadcast> and <Subscriber> components,
we provide a createBroadcast function that may be used to create them.

See the README for further usage instructions.

@reactjs reactjs locked as resolved and limited conversation to collaborators Feb 2, 2018

@gaearon

This comment has been minimized.

Member

gaearon commented Feb 2, 2018

The RFC has been finalized and implemented (with a functional children prop).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.