繁体   English   中英

null 类型的参数不可分配给 RadioGroupState 类型的参数

[英]Argument of type null is not assignable to parameter of type RadioGroupState

我正在尝试使用 React-Aria 在 Typescript 中构建一个设计系统,但我在使用 Radio 组件时遇到了一些问题。

我尝试尽可能多地遵循 该示例,但最终得到: Argument of type 'null' is not assignable to parameter of type 'RadioGroupState'. 而且我不明白如何解决这个问题,有人对我有什么建议吗?

这是我的代码:

import { VisuallyHidden } from '@react-aria/visually-hidden';
import { useFocusRing } from '@react-aria/focus';
import { useRadioGroup, useRadio } from '@react-aria/radio';
import { useRadioGroupState } from '@react-stately/radio';
import { AriaRadioGroupProps } from '@react-types/radio';
import { AriaRadioProps } from '@react-types/radio';

let RadioContext = React.createContext(null);

interface RadioGroupProps extends AriaRadioGroupProps {
  children: React.ReactNode;
}

interface RadioProps extends AriaRadioProps {
  children: React.ReactNode;
}

function RadioGroup(props: RadioGroupProps) {
  let { children, label, isDisabled, defaultValue } = props;
  let state = useRadioGroupState(props);
  let { radioGroupProps, labelProps } = useRadioGroup(props, state);

  return (
    <div {...radioGroupProps}>
      <span {...labelProps}>{label}</span>
      <RadioContext.Provider value={state}>{children}</RadioContext.Provider>
    </div>
  );
}

function Radio(props: RadioProps) {
  let { children } = props;
  let state = React.useContext(RadioContext);
  let ref = React.useRef(null);

  let { inputProps } = useRadio(props, state, ref);
  let { isFocusVisible, focusProps } = useFocusRing();

  let isSelected = state.selectedValue === props.value;
  let strokeWidth = isSelected ? 2 : 2;

  return (
    <label
      className={`${state.isDisabled ? 'cursor-not-allowed' : ''}`}
      style={{ display: 'flex', alignItems: 'center' }}
    >
      <VisuallyHidden>
        <input {...inputProps} {...focusProps} ref={ref} />
      </VisuallyHidden>
      <svg width={24} height={24} aria-hidden="true" style={{ marginRight: 4 }}>
        <circle
          cx={12}
          cy={12}
          r={8 - strokeWidth / 2}
          fill="none"
          stroke={isSelected ? 'red' : '#BBBBBB'}
          strokeWidth={strokeWidth}
        />
        {isSelected && (
          <path transform="translate(5.5 5)" d={`M 4 3 A 1 1 0 0 0 9 11 A 1 1 0 0 0 4 3`} fill="#F70000" />
        )}
      </svg>
      <div className={`${state.isDisabled ? 'text-grey-disabled cursor-not-allowed' : ''}`}>{children}</div>
    </label>
  );
}

export { Radio, RadioGroup };

我这样解决了这个问题:

  1. @react-stately/radio导入RadioGroupState
  2. 为上下文组件分配了以下类型:
    let RadioContext = createContext<RadioGroupState | null>(null);
  3. 使用null可能性分配上下文变量:
    let stateOrNull = useContext(RadioContext);
  4. 分配state变量并将其转换为RadioGroupState类型:
    let state = stateOrNull as RadioGroupState;

代码沙盒

import { createContext, useContext, useRef } from "react";
import { VisuallyHidden } from "@react-aria/visually-hidden";
import { useFocusRing } from "@react-aria/focus";
import { useRadioGroup, useRadio } from "@react-aria/radio";
import { RadioGroupState, useRadioGroupState } from "@react-stately/radio";
import { AriaRadioGroupProps, AriaRadioProps } from "@react-types/radio";

let RadioContext = createContext<RadioGroupState | null>(null);

interface RadioGroupProps extends AriaRadioGroupProps {
  children: React.ReactNode;
}

interface RadioProps extends AriaRadioProps {
  children: React.ReactNode;
}

function RadioGroup(props: RadioGroupProps) {
  let { children, label } = props;
  let state = useRadioGroupState(props);
  let { radioGroupProps, labelProps } = useRadioGroup(props, state);

  return (
    <div {...radioGroupProps}>
      <span {...labelProps}>{label}</span>
      <RadioContext.Provider value={state}>{children}</RadioContext.Provider>
    </div>
  );
}

function Radio(props: RadioProps) {
  let { children } = props;
  let stateOrNull = useContext(RadioContext);
  let state = stateOrNull as RadioGroupState;
  let ref = useRef(null);

  let { inputProps } = useRadio(props, state, ref);
  let { focusProps } = useFocusRing();

  let isSelected = state.selectedValue === props.value;
  let strokeWidth = isSelected ? 2 : 2;

  return (
    <label
      className={`${state.isDisabled ? "cursor-not-allowed" : ""}`}
      style={{ display: "flex", alignItems: "center" }}
    >
      <VisuallyHidden>
        <input {...inputProps} {...focusProps} ref={ref} />
      </VisuallyHidden>
      <svg width={24} height={24} aria-hidden="true" style={{ marginRight: 4 }}>
        <circle
          cx={12}
          cy={12}
          r={8 - strokeWidth / 2}
          fill="none"
          stroke={isSelected ? "red" : "#BBBBBB"}
          strokeWidth={strokeWidth}
        />
        {isSelected && (
          <path
            transform="translate(5.5 5)"
            d={`M 4 3 A 1 1 0 0 0 9 11 A 1 1 0 0 0 4 3`}
            fill="#F70000"
          />
        )}
      </svg>
      <div
        className={`${
          state.isDisabled ? "text-grey-disabled cursor-not-allowed" : ""
        }`}
      >
        {children}
      </div>
    </label>
  );
}

export { Radio, RadioGroup };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM