Skip to content
This repository has been archived by the owner on Dec 16, 2021. It is now read-only.

Missing createContext #475

Closed
Pyrolistical opened this issue Jun 8, 2018 · 15 comments
Closed

Missing createContext #475

Pyrolistical opened this issue Jun 8, 2018 · 15 comments

Comments

@Pyrolistical
Copy link

Pyrolistical commented Jun 8, 2018

React libraries that use the new Context API will have import {createContext} from 'react', and that
doesn't work with preact-compat

Should we just re-export https://github.com/valotas/preact-context while we wait for createContext to be added to preact preactjs/preact#963?

@Pyrolistical Pyrolistical changed the title Forward createContext to preact-context Missing createContext Jun 8, 2018
@kontrollanten
Copy link

I'm missing createContext too. @Pyrolistical, what do you mean with "re-export"? I'm looking for a workaround until we've something merged in preact or preact-compat.

@mindplay-dk
Copy link

I didn't know preact-context existed!

The fact that this exists really should be documented somewhere in plain sight.

I was beginning to worry that Preact and React were about to diverge too substantially with the introduction of the new context API in React - and also have been looking for a simple solution for application-wide shared state. This looks great!

@developit
Copy link
Member

There's some funky bitmask stuff in preact-context that I'm not super sure we need in preact-compat (it doesn't seem to be part of the officially supported React API). Perhaps we could just add something like this?

function createContext(initialValue) {
  const key = `$ctx-${++counter}`;
  class Provider {
    getChildContext() {
      let ctx = this.ctx || (this.ctx = {});
      if (ctx[key]!==this.props.value) {
        for (let i=0; i<subs.length; i++) subs[i].setState(null);
      }
      ctx[key] = this.props.value;
      return ctx;
    }
    render(props) {
      return props.children[0];
    }
  }
  class Consumer extends Component {
    componentDidMount() {
      consumers.push(this);
    }
    componentWillUnmount() {
      consumer.splice(consumers.indexOf(this), 1);
    }
    render(props, state, context) {
      return this.props.children[0](key in context ? context[key] : initialValue);
    }
  }
  return { Provider, Consumer };
}

@kontrollanten
Copy link

I've been thinking a bit about this while I've been working on different projects using both React and preact and I'm not sure that I really want this feature into preact anymore.

What I really fell for with preact/React is the inspiration of functional programming and it's "simplicity", in the meaning that without side effects it's really easy to isolate, debug and understand the web clients. Compared to for instance Angular it's, in my opinion, a huge difference in the complexity. My picture is that React now is moving away from this approach and starts to implement side effects in the framework (context), and what I've heard there's more new features to come.

Of course side effects can make web apps easier to build, and also remove complexity. But I think that with the tools to create side effects developers will tend to use those as shortcuts in cases where pure functional programming can solve the same issue. The price for the developers (and the projects) is technical debt.

With the background of this I can really see a purpose with preact not following this trend. I guess the purpose of creating a preact API similar to React was easy migration between those frameworks, but now preact is pretty big and maybe this can be a start for a diverge between those two frameworks where it's not longer obvious that preact should try to follow Reacts pattern.

What do you think?

@mindplay-dk
Copy link

@kontrollanten side-effects is not the only use for this - I'm using it simply as a means of sharing state between related components, e.g. a <TabList> with <Tab> panels, where the panels can share the selected tab state, which is provided by the parent tab-list. (even works fine for nested tabs.)

I guess the purpose of creating a preact API similar to React was easy migration between those frameworks, but now preact is pretty big and maybe this can be a start for a diverge between those two frameworks where it's not longer obvious that preact should try to follow Reacts pattern.

Isn't that why we have preact-compat?

@developit most likely we're talking about an addition to that, not an addition to the framework itself?

I think it's very important to have that feature in preact-compat - the whole point of that package existing, is to provide API-compatible React idioms, and I think there's no doubt the new context API is already a popular idiom in React?

@Pyrolistical
Copy link
Author

yeah, the more I look at preact, the more I think preact should just do its own thing.

Even react regrets the move from createClass to es6 classes, so they are not infallible.

I would love to see preact do its own thing and continue with ideas like having props/state as params in render and simplifying children.

I want preact to be different enough that we won't expect compat at all

@kontrollanten
Copy link

kontrollanten commented Jul 12, 2018

@kontrollanten side-effects is not the only use for this - I'm using it simply as a means of sharing state between related components, e.g. a with panels, where the panels can share the selected tab state, which is provided by the parent tab-list. (even works fine for nested tabs.)

@mindplay-dk That's true, but I think my reasons applies for those cases also; it's no longer functional and my opinion is that this behaviour will in many cases increase application complexity.

Isn't that why we have preact-compat?

I was mainly thinking about implementing context API into preact, maybe I should've created this discussion on preact project but I guess that a decision like this will affect both preact and preact-compat.

One way could be to keep preact-compat up to date with latest React features and keep preact slimmed. I'd love a clear distinguish between those projects; where preact strives for a petite, functional rendering framework and preact-compat makes preact easier to use for those who needs React's features, being able to import them one by one.

@developit
Copy link
Member

developit commented Aug 6, 2018

I'm partial to the idea of exporting createContext from preact-compat, and also shipping it as a standalone module (or just pointing to preact-context). It's another dependency for Preact core users, but I think most people actually prefer small composable dependencies at this point.

Going forward, I think the main metric we want to use for whether things get bundled into Preact itself is actually whether they can feasibly be implemented as standalone modules. Something like the new Context API is actually designed to be a standalone module, and nice implementations exist. Something like createRef() is a bit less clear-cut, since Preact could support it in ~40 bytes with the same semantics as React. Supporting createRef as an add-on module is smaller, but the value returned by createRef is a function rather than an Object.

As for preact-compat, I'd like to move the React 0.14.x features into a separate module, a "legacy" version, or just remove them entirely. List-based features like the React.DOM.div factories are just wasteful, and we're putting them into bundles knowing most people will never use them. I'd rather save those bytes for new features, or just give folks some bytes back :)

@developit
Copy link
Member

For those finding this issue, please use styled-components@3 for now.

ebkn added a commit to ebkn/ebkn.github.io that referenced this issue Feb 7, 2019
@moshest
Copy link

moshest commented Feb 17, 2019

@developit I think that we should let the bundlers with the tree-shake functionality to save more bytes when removing createContext and other methods and focus on making this package simple and easy to use.

Right now I'm using the following "pollyfill" for React 16:

$ npm i create-react-context create-react-ref
// preact-compat.js
import React from 'preact-compat';

export default React;
export * from 'preact-compat';

const createContext = require('create-react-context');
const forwardRef = require('create-react-ref/lib/forwardRef');
const createRef = require('create-react-ref/lib/createRef');

export { createContext };

React.createContext = createContext;
React.forwardRef = forwardRef;
React.createRef = createRef;

Then, on webpack:

  resolve: {
    alias: {
      react: path.join(__dirname, 'preact-compat.js'),
      'react-dom': path.join(__dirname, 'preact-compat.js'),
    },
  }

@marvinhagemeister
Copy link
Member

createContext is available in Preact X. An alpha is already out on npm. Even more exciting is that we moved compat into the core repo. Changing preact-compat to preact/compat in your require or import statements is all that's needed to be able to use createContext.

@ko06
Copy link

ko06 commented Aug 10, 2019

Can we use the styled component 4.0.0 in preact?

@fyi,
it working perfectly on 3.4.9.

can anyone suggest me the approach?

Screenshot 2019-08-10 at 6 42 28 PM
Screenshot 2019-08-10 at 6 42 16 PM
Screenshot 2019-08-10 at 6 41 48 PM

@marvinhagemeister
Copy link
Member

For styled-components V4 to work with Preact you need to upgrade to the upcoming Preact version (currently in the release candidate phase).

@ko06
Copy link

ko06 commented Aug 10, 2019

Is there anyway achieve in preat 8 version?

@marvinhagemeister
Copy link
Member

No.

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

No branches or pull requests

7 participants