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

Accept generics in hook #110

Closed
yuritoledo opened this issue Jun 9, 2020 · 8 comments
Closed

Accept generics in hook #110

yuritoledo opened this issue Jun 9, 2020 · 8 comments
Labels
enhancement New feature or request

Comments

@yuritoledo
Copy link

yuritoledo commented Jun 9, 2020

Hey!

Actually I am using const list = useList()

function useListContext() {
  const [data, setData] = useState([])

 
  // ommited

  return {
    data,
    feedData,
  }
}

export const [
  ListProvider,
  useList, // I want to pass the generics to this hook, to use in setData state
] = constate(useListContext)

There are any support like these in your roadmap?

Thanks

@diegohaz
Copy link
Owner

diegohaz commented Jun 9, 2020

I don't understand what you mean. Could you elaborate?

@yuritoledo
Copy link
Author

yuritoledo commented Jun 10, 2020

Sure, is something like this:

// page_component.ts

type TOrders = {
  foo: string,
  bar: boolean
}

const list = useList<TOrders[]>()

typeof list.data === TOrders[]

// hook_component.ts

function useListContext<T>() {
  const [data, setData] = useState(T[])

 
  // ommited

  return {
    data,
    feedData,
  }
}

export const [
  ListProvider,
  useList,
] = constate(useListContext)

Today, constate doesn't accept this.

Is it better now?

@diegohaz
Copy link
Owner

diegohaz commented Jun 10, 2020

Got it! Thanks!

I don't know if that's possible. But if you know how to implement that, I would accept a PR.

Right now, the only solution I can think of is casting the function in your app:

const [ListProvider, _useList] = constate(useListContext);

export const useList = _useList as <T>() => T[];

@diegohaz diegohaz added the enhancement New feature or request label Jun 10, 2020
@yuritoledo
Copy link
Author

Great, I will check how this cast implementation works here.

And I will try to find some way to open a PR, i really like this lib.

Thank you for your attention!

@caasi
Copy link

caasi commented Jun 11, 2020

Is this possible by change these:

function createUseContext(context: React.Context<any>): any {
  return () => {
    const value = React.useContext(context);
    if (isDev && value === NO_PROVIDER) {
      // eslint-disable-next-line no-console
      console.warn("[constate] Component not wrapped within a Provider.");
    }
    return value;
  };
}

// ...

function constate<P, V, S extends Array<SplitValueFunction<V>>>(
  useValue: (props: P) => V,
  ...splitValues: S
): ContextHookReturn<P, V, S> {
  const Context = React.createContext(NO_PROVIDER as V);
  // ...
  const useContext: any = () => {
    if (isDev) {
      // eslint-disable-next-line no-console
      console.warn(
        "[constate] Using the return value of constate as a hook is deprecated. " +
          "Please, use the tuple format instead. " +
          "See instructions on https://github.com/diegohaz/constate/pull/101"
      );
    }
    return createUseContext(Context)();
  };
 // ...
}

to:

function createUseContext(context: React.Context<T>): T {
  return () => {
    const value = React.useContext(context);
    if (isDev && value === NO_PROVIDER) {
      // eslint-disable-next-line no-console
      console.warn("[constate] Component not wrapped within a Provider.");
    }
    return value;
  };
}

// ...

function constate<P, V, S extends Array<SplitValueFunction<V>>>(
  useValue: (props: P) => V,
  ...splitValues: S
): ContextHookReturn<P, V, S> {
  const Context = React.createContext(NO_PROVIDER as V); // as React.Context<V>
  // ...
  const useContext: V = () => {
    if (isDev) {
      // eslint-disable-next-line no-console
      console.warn(
        "[constate] Using the return value of constate as a hook is deprecated. " +
          "Please, use the tuple format instead. " +
          "See instructions on https://github.com/diegohaz/constate/pull/101"
      );
    }
    return createUseContext(Context)();
  };
 // ...
}

I am sorry that I am unable to create a real patch right now.

@mayteio
Copy link

mayteio commented Jul 21, 2021

Additionally, it would be great to pass generics to the Provider (current types don't like it). Here's a trivial codesandbox showing the issue.

import constate from "constate";

type UseGenericProps<G> = {
  custom: G;
};

export function useGenericExample<Generic extends string>({
  custom
}: UseGenericProps<Generic>) {
  return custom;
}

export const [GenericProvider, useGeneric] = constate(
  // TS Error 1
  useGenericExample
);

function Consumer() {
  // type is `unknown`
  const value = useGeneric();
  return <>{value}</>;
}

export default function App() {
  return (
    <GenericProvider<
      // TS error 2
      "type-argument"
    > custom="type-argument">
      <Consumer />
    </GenericProvider>
  );
}

TS Error 1;

function useGenericExample<Generic extends string>({ custom }: UseGenericProps<Generic>): Generic
Argument of type '<Generic extends string>({ custom }: UseGenericProps<Generic>) => Generic' is not assignable to parameter of type '(props: unknown) => string'.
  Types of parameters '__0' and 'props' are incompatible.
    Type 'unknown' is not assignable to type 'UseGenericProps<string>'. ts(2345)

TS Error 2;

Expected 0 type arguments, but got 1.ts(2558)

@onionhammer
Copy link

It would be great if this were supported

@jsutaria
Copy link

jsutaria commented Nov 7, 2023

Also would love if this was supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants