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

Cannot use memoCustomCompareProps #422

Closed
benadamstyles opened this issue May 5, 2019 · 6 comments · Fixed by #766
Closed

Cannot use memoCustomCompareProps #422

benadamstyles opened this issue May 5, 2019 · 6 comments · Fixed by #766
Labels
bug help wanted ppx issues related to the reason-react ppx

Comments

@benadamstyles
Copy link

Attempting to use React.memoCustomCompareProps throws the following compiler error:

Invalid_argument("react.component calls can only be on function definitions or component wrappers (forwardRef, memo).")

@benadamstyles
Copy link
Author

The same is true of React.Context.provider(context)

@rickyvetter
Copy link
Contributor

Can you give an example of how context was giving you trouble? It can work fine if you drop out of JSX with something like


let context = React.createContext(defaultContextValue);
React.Context.provider(context);

[@react.component]
let make = (~val, ~children) => {
  React.createElement(
    provider,
    {"value": ~val, "children": children},
  );
};

Or if you copy over the make + makeProps directly from provider.

Looking at memoCustomCompareProps!

@tizoc
Copy link

tizoc commented Jun 19, 2019

@rickyvetter do you know if the current context API is final? It is a bit cumbersome and not obvious right now. Since it is not documented yet and was not mentioned in the release notes I guess it is still a work in process.

These two options work right now:

module Provider = {
  let provider = React.Context.provider(context);

  [@react.component]
  let make = (~value, ~children) => {
    React.createElement(provider, {"value": value, "children": children});
  };
};

and

module Provider = {
  let makeProps = (~value, ~children, ()) => {
    "value": value,
    "children": children,
  };
  let make = React.Context.provider(context);
};

but thats kind of "manual", I was expecting something similar to:

module Provider =
  React.Context.Provider.Make({
    type t = int;
    let context = React.createContext(0);
  });

implemented like:

module type S = {
  type t;
  let context: React.Context.t(t);
};

module Make = (C: S) => {
  let makeProps = (~value, ~children, ()) => {
    "value": value,
    "children": children,
  };
  let make = React.Context.provider(context);
};

or maybe for the whole context bundle to be created with a functor (resulting in a module with Consumer/Provider submodules)

@tizoc
Copy link

tizoc commented Jun 19, 2019

Functor bundling everything:

module type CONFIG = {
  type t;
  let initialValue: t;
};

module Make = (Config: CONFIG) => {
  type t = Config.t;

  let context = React.createContext(Config.initialValue);
  let use = () => React.useContext(context);

  module Provider = {
    [@react.component]
    let make = {
      let provider = React.Context.provider(context);

      (~value=Config.initialValue, ~children) => {
        React.createElement(
          provider,
          {"value": value, "children": children},
        );
      };
    };
  };

  module Consumer = {
    [@react.component]
    let make = (~children) => <> {children(use())} </>;
  };
};

Example

module MyContext =
  Context.Make({
    type t = string;
    let initialValue = "hello";
  });

then

<MyContext.Provider value="Bye">
  <MyContext.Consumer>
    {value => s(value)}
  </MyContext.Consumer>
</MyContext.Provider>

and also

let myContext = MyContext.use();
// or
let myContext = React.useContext(MyContext.context);

@benadamstyles
Copy link
Author

benadamstyles commented Apr 19, 2020

I've found a workaround for this, which is so simple that it suggests changing this in reason-react itself might be a single line change somewhere (will see if I can PR this separately):

let memo = React.memoCustomCompareProps(_, (_, _) => true);

[@react.component]
let make = memo(() => <View />);

EDIT: I've had a look at the ppx code and I'm afraid it's beyond me!

@peterpme peterpme added bug help wanted ppx issues related to the reason-react ppx labels Apr 22, 2020
@jfrolich
Copy link

Would be good to find a fix for this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug help wanted ppx issues related to the reason-react ppx
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants