【问题标题】:React context with generics使用泛型反应上下文
【发布时间】:2020-06-28 17:24:35
【问题描述】:

我们如何在 React.CreateContext 中使用泛型?

我有这个:

interface Props {
}

export interface SearchContextProps {
  dtos: any[];
}

export const SearchContext = React.createContext<SearchContextProps>({
  dtos: []
});

const SearchPage: React.FunctionComponent<Props> = (props) => {
  const [dtos, setDtos] = React.useState<any[]>([]);

  const searchContext = {
    dtos: dtos
  };

  return (
    <SearchContext.Provider value={searchContext}>
      ...
    </SearchContext.Provider>
  );
}

export default SearchPage;

现在我想使用泛型,所以我会写如下内容:

interface Props<T> {
}

export interface SearchContextProps<T> {
  dtos: T[];
}

export const SearchContext = React.createContext<SearchContextProps<T>>({
  dtos: []
});

const SearchPage = <T extends object>(props: Props<T>) => {
  const [dtos, setDtos] = React.useState<T[]>([]);

  const searchContext = {
    dtos: dtos
  };

  return (
    <SearchContext.Provider value={searchContext}>
      ...
    </SearchContext.Provider>
  );
}

export default SearchPage;

但我不知道如何去上班:

export const SearchContext = React.createContext<SearchContextProps<T>>({

如何在此处使用泛型,如何访问 T?

我试图在组件内移动上下文:

interface Props<T> {
}

export interface SearchContextProps<T> {
  dtos: T[];
}

const SearchPage = <T extends object>(props: Props<T>) => {
  const [dtos, setDtos] = React.useState<T[]>([]);

  const SearchContext = React.createContext<SearchContextProps<T>>({
    dtos: [],
  });

  const searchContext = {
    dtos: dtos,
  };

  return (
    <SearchContext.Provider value={searchContext}>
      ...
    </SearchContext.Provider>
  );

}

export default SearchPage;

但现在我不知道如何导出它。

有什么帮助吗?

【问题讨论】:

  • 嗨 Simone,我目前正在处理相同的主题。你找到解决方案了吗?
  • 是的,看我自己的回答。

标签: reactjs typescript generics react-context


【解决方案1】:

我最终得到:

import * as React from 'react';

interface Props<T> {}

export interface SearchContextProps<T> {
  dtos: T[];
}

export const SearchContext = React.createContext<SearchContextProps<any>>({
  dtos: [],
});

const SearchPage = <T extends object>(props: React.PropsWithChildren<Props<T>>) => {
  const [dtos, setDtos] = React.useState<T[]>([]);

  const searchContext = {
    dtos: dtos,
  };

  return <SearchContext.Provider value={searchContext}>...</SearchContext.Provider>;
};

export default SearchPage;

还有消费者

const searchContext = React.useContext<SearchContextProps<Interfaces.FileDto>>(SearchContext)

【讨论】:

  • 能否添加 SearchContext.Consumer 的示例?
  • React.useContext>(SearchContext)
  • 谢谢你,操作!非常简单,就我而言,我的 Context 类型中有很多不受泛型类型影响的属性,因此在仅使用上下文中的那些非泛型属性的组件中,我什至在调用时都没有指定类型useContext.
【解决方案2】:

我也一直在尝试解决这个问题,最后用我正在构建 atm 的向导解决了这个问题。

提供者部分和你的类似:

import React, { Dispatch, SetStateAction } from "react";

export interface IWizardContext<T> {
  formData: T;
  setFormData: Dispatch<SetStateAction<T>>;
}

export const WizardContext = React.createContext<IWizardContext<any>>({
  formData: {},
  setFormData: () => {},
});

const WizardProvider: React.FC = (props) => {
  const [formData, setFormData] = React.useState<any>({});

  return (
    <WizardContext.Provider
      value={{
        formData: formData,
        setFormData: setFormData,
      }}
    >
      {props.children}
    </WizardContext.Provider>
  );
};

export default WizardProvider;

export function withWizardProvider<TProps = {}>(component: React.FC<TProps>) {
  const Component = component;

  return ((props: TProps) => {
    return (
      <WizardProvider>
        <Component {...props} />
      </WizardProvider>
    );
  }) as React.FC<TProps>;
}

消费者:

import React from "react";
import {
  IWizardContext,
  withWizardProvider,
  WizardContext,
} from "./WizardProvider";

interface ISampleWizardState {
  name?: string;
  lastName?: string;
}

const SampleWizard: React.FC = (props) => {
  const wizard = React.useContext<IWizardContext<ISampleWizardState>>(
    WizardContext
  );

  return (
    <div
      style={{
        display: "flex",
        justifyContent: "flex-start",
        flexDirection: "column",
      }}
    >
      <span>{`${wizard.formData.name || "John"} ${
        wizard.formData.lastName || "Doe"
      }`}</span>
      <input
        type="text"
        name="name"
        value={wizard.formData.name}
        onChange={(e) => {
          const text = e?.target?.value;
          wizard.setFormData((prev) => ({
            ...prev,
            name: text,
          }));
        }}
      />
      <input
        type="text"
        name="lastName"
        value={wizard.formData.lastName}
        onChange={(e) => {
          const text = e?.target?.value;
          wizard.setFormData((prev) => ({
            ...prev,
            lastName: text,
          }));
        }}
      />
    </div>
  );
};

export default withWizardProvider(SampleWizard);

所以对消费者来说最主要的是在useContext中定义你的T:

React.useContext<IWizardContext<ISampleWizardState>>(WizardContext);

【讨论】:

    猜你喜欢
    • 2019-05-31
    • 2011-05-11
    • 2021-07-22
    • 2021-02-03
    • 1970-01-01
    • 2020-01-01
    • 2019-03-06
    • 2020-11-05
    • 1970-01-01
    相关资源
    最近更新 更多