Как можно реализовать функцию React buildContext, которая принимает обобщенный c хук в качестве параметра? - PullRequest
0 голосов
/ 15 января 2020

Привет всем умным людям здесь при переполнении стека.

Я хотел бы написать универсальную c buildContext служебную функцию с использованием машинописного текста, которая принимает хук в качестве параметра и возвращает объект, содержащий Provider, Consumer, useState и useActions, но я не вижу, как заставить его поддерживать обобщенные c хуки.

В настоящее время у меня есть рабочая buildContext вспомогательная функция, поддерживающая хуки, которые не является общим c. Он поддерживает взятие хука в качестве параметра и возврат вышеупомянутого объекта.

Ниже следует код для реализации этой функции полезности:

import * as React from "react";

type Function<S, A, P> = (props: P) => { state: S; actions: A };

export default function buildContext<S, A, P extends object>(
  useHook: Function<S, A, P>
) {
  const StateContext = React.createContext<S | undefined>(undefined);
  const ActionsContext = React.createContext<A | undefined>(undefined);

  const Provider: React.SFC<P> = ({ children, ...props }) => {
    const { state, actions } = useHook(props as P);

    return (
      <StateContext.Provider value={state}>
        <ActionsContext.Provider value={actions}>
          {children}
        </ActionsContext.Provider>
      </StateContext.Provider>
    );
  };

  const useState = () => {
    const context = React.useContext(StateContext);
    if (context === undefined) {
      throw Error("Missing Provider for useState");
    }
    return context;
  };

  const useActions = () => {
    const context = React.useContext(ActionsContext);
    if (context === undefined) {
      throw Error("Missing Provider for useActions");
    }
    return context;
  };

  const StateConsumer: React.SFC<{
    children: ({ state }: { state: S }) => React.ReactNode;
  }> = ({ children }) => {
    return (
      <StateContext.Consumer>
        {state => {
          if (state === undefined) {
            throw Error("Missing Provider for StateConsumer");
          }
          return children({ state });
        }}
      </StateContext.Consumer>
    );
  };
  const ActionsConsumer: React.SFC<{
    children: ({ actions }: { actions: A }) => React.ReactNode;
  }> = ({ children }) => {
    return (
      <ActionsContext.Consumer>
        {actions => {
          if (actions === undefined) {
            throw Error("Missing Provider for ActionsConsumer");
          }
          return children({ actions });
        }}
      </ActionsContext.Consumer>
    );
  };

  return {
    Provider,
    useState,
    useActions,
    StateConsumer,
    ActionsConsumer
  };
}

Функцию полезности можно найти здесь, с коротким примером: github / build-context

Я хотел бы иметь возможность сделать что-то похожее на это:

function useTest<T>(props: { thing: T }) {
  return {
    state: { thing: props.thing },
    actions: {},
  }
}

const Context = buildContext(useTest)

// Thought 1
const Component = (props) => (
  <Context.Provider thing={'ball'}> // 'ball' here could be anything
    <Context.Consumer>
    {props => (
      <div>{props.thing}</div>
    )}
    </Context.Consumer>
  </Context.Provider>
  const { thing } = Context.useState()
)

// Thought 2
const Component = (props) => (
  <Context.Provider<string> thing={'ball'}> // 'ball' here needs to be a string
    <Context.Consumer>
    {props => (
      <div>{props.thing}</div>
    )}
    </Context.Consumer>
  </Context.Provider>
  const { thing } = Context.useState()
)

I'm благодарен за всю помощь, которую я могу получить, ура!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...