【问题标题】:Type or interface for location.state in react-routerreact-router 中 location.state 的类型或接口
【发布时间】:2020-06-20 12:36:03
【问题描述】:

在一个组件中,有一个 <Link>(来自 react-router-dom)在 state 属性中传递一个对象。

另一个名为ReceiverComponent 的组件正在正确接收该对象。但是,下面的代码抱怨消息:

类型“PoorMansUnknown”不可分配给类型“locationStateProps”。 类型“未定义”不可分配给类型 'locationStateProps'.ts(2322)

type locationStateProps = {
  name: string;
}

function ReceiverComponent() {
  const location = useLocation();
  const myState: locationStateProps = location.state;
  return (
    <div>
      {myState.name}
    </div>
  );
}

我需要以某种方式为状态提供一种类型,而不会出现此错误。如何进行?

【问题讨论】:

  • state 可以未定义,因此会出现错误。如果您绝对确定它总是有一个值,您可以使用非空断言运算符:const myState: locationStateProps = location.state!;
  • 我不知道非空断言运算符。谢谢。
  • 考虑将变量输入为const myState: locationStateProps | undefined = ...,然后输入{myState?.name} 或类似的东西,以防状态未定义
  • 好的,这很有帮助。到目前为止,我一直在使用 jsx 进行开发,最近更改为 typescript 并习惯了它。所有的信息都是有帮助的。谢谢。

标签: reactjs typescript react-router react-router-dom


【解决方案1】:

在 Github 上有一个关于这个问题的 thread

我实现了线程中提到的这个解决方案并且它有效。

interface Props extends RouteComponentProps<
  { myParamProp?: string }, // props.match.params.myParamProp
  any, // history
  { myStateProp?: string }, // props.location.state.myStateProp
> {
  myNormalProp: boolean;
}

【讨论】:

    【解决方案2】:

    您还可以构建自己的状态接口并将其转换为:

    interface CustomState {
      ...
    }
    
    const location = useLocation()
    const state = location.state as CustomState
    

    【讨论】:

      【解决方案3】:

      对于可能最终出现在这里的其他人......我正在使用 React Router v6,据我所知,它不再导出 RouteComponentProps(我安装了 @types/react-router 和 @types/react-router -dom - 我在DefinitelyTyped 文件中看到了类型定义,但没有从react-router-dom 导出)。

      所以,Location 的输入方式,我发现自己无法以安抚 Typescript 的方式扩展它。不过……

      我不推荐 as 强制转换,因为它会降低 TypeScript 的效率。好消息!您可以使用 is 而不是 as 来向 TypeScript 证明给定元素确实是您所说的那样。例如:

      type LocationStateProps = {
        name: string;
      }
      
      function ReceiverComponent() {
        const location = useLocation();
        const myState = location.state;
      
        // note that you are defining the return type of this function using `is`
        const hasNameProps = (state: object | null | LocationStateProps): state is LocationStateProps => {
          // you use `as` here, but only so typescript doesn't yell at you while you access the property
          // specifically to test if it is there
          return (state as LocationStateProps).name !== undefined;
        }
      
      
        return (
          <div>
            {/**
             * Now you can check to see if the prop exists. If it does, us it confidently, and TypeScript won't
             * complain! But you're able to provide a fallback in case the value is, for some reason, not there.
             * If you as-cast, you lose that opportunity. It's a little verbose, but it preserves the benefit of
             * TypeScript... Type safety!
             */}
            {hasNameProps(myState) ? myState.name : "No Name"}
          </div>
        );
      }
      

      【讨论】:

        【解决方案4】:

        对我有用

           interface locationStateProps {
          from: { isEditing: string }
        }
        const NewPublication: React.FC<NewPublicationProps> = () => {
          const navigate = useNavigate();
        
          let location = useLocation();
          const myState: locationStateProps = location.state as locationStateProps;
        

        【讨论】:

        • 写出完美的代码格式加上大括号。
        • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
        猜你喜欢
        • 1970-01-01
        • 2017-02-27
        • 2020-03-28
        • 2017-04-27
        • 2011-03-30
        • 1970-01-01
        • 2020-06-06
        • 2022-01-19
        • 2011-02-10
        相关资源
        最近更新 更多