Привет всем умным людям здесь при переполнении стека.
Я хотел бы написать универсальную 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 благодарен за всю помощь, которую я могу получить, ура!