react + ts 类型检测问题?求解答。

2020-07-04 17:29:46 +08:00
 loveyou1

基础代码

import React from 'react';

interface Prop {
  children: React.ReactNode
}


class Person extends React.Component<Prop, {}> {
  constructor(props: Prop) {
    super(props);
    this.state = {};
  }
  
  render() {
    return (
      <div>
        // 这个地方报错
        { this.props.children({ x: 30, y: 40 }) }
      </div>
    );
  }
}

报错内容

(property) React.Component<Prop, {}, any>.props: Readonly<Prop> & Readonly<{
    children?: React.ReactNode;
}>
不能调用可能是 "null" 或“未定义”的对象。ts(2723)
(property) children: React.ReactNode
不能调用可能是 "null" 或“未定义”的对象。ts(2723)
此表达式不可调用。
  不可调用 "string | number | boolean | {} | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)> | ReactNodeArray | ReactPortal" 类型的任何组成部分。ts(2349)

另一种写法,不报错

import React from 'react';

interface Prop {
  children: React.ReactNode
}


class Person extends React.Component<Prop, {}> {
  constructor(props: Prop) {
    super(props);
    this.state = {};
  }

  render() {
    const props: any = this.props;
    return (
      <div>
         // 这样不会报错
        { props.children({ x: 30, y: 40 }) }
      </div>
    );
  }
}

问题

** 勿喷我,觉得问题简单,不愿意回复的请退出去 **

3301 次点击
所在节点    问与答
15 条回复
BigOldBrother
2020-07-04 17:51:42 +08:00
我理解的你只是给 constructor 函数的 props 参数定义了类型,下边的 this.props 是实例上的了,不是一个东西
loveyou1
2020-07-04 18:05:11 +08:00
@BigOldBrother

import React from 'react';

interface Prop {
children: React.ReactNode
}


class Person extends React.Component<Prop, {}> {
constructor(props: Prop) {
super(props);
this.state = {};
}

render() {
// 这里这样
const props: Prop = this.props;
return (
<div>
{ props.children({ x: 30, y: 40 }) }
</div>
);
}
}

这种情况也报错
withzhaoyu
2020-07-04 18:10:47 +08:00
children 断言是 reactNode, 其实是个方法?我看你有传参 {x:30,y:40}
toma77
2020-07-04 18:11:49 +08:00
children 换个名字试试?
loveyou1
2020-07-04 18:15:05 +08:00
@withzhaoyu
我就想试一试 react + ts,谁知道一试就出问题
因为这个组件是这么写的
<Person>
{(mouse: any) => (
<p>鼠标的位置是 {mouse.x},{mouse.y}</p>
)
</Person>
loveyou1
2020-07-04 18:15:57 +08:00
@toma77
换不了吧,children 就是代表组件内部的节点
sun876592293
2020-07-04 18:20:54 +08:00
this 调用的是类成员,你得看看子类和父类有没有这个成员,不是声明了 传个形参就行的
Raincal
2020-07-04 18:48:24 +08:00
```js
children: (mouse: { x: number; y: number }) => React.ReactNode
```
noe132
2020-07-04 18:51:48 +08:00
如果是 React.ReactNode 请直接{this.props.children}
如果你要传个 render function 进来,请把 children 的类型改了。

另外不推荐这样做,建议用 render props.
dremy
2020-07-04 18:58:39 +08:00
这不就是 children 版的 render props,那得把 children 定义成对应的函数类型

另外现在的 Hooks 解决这类问题更加合适和方便,建议通过自定义 Hooks 而不是通过类组件的 render props 来实现
loveyou1
2020-07-04 19:04:20 +08:00
@Raincal 这个 🆗,不懂就问,为啥 children: React.ReactNode 这个 this.props 就报错了
@noe132 我就试着玩,正式写不会这么写
loveyou1
2020-07-04 19:07:27 +08:00
@dremy 我就试着玩的
Raincal
2020-07-04 19:21:05 +08:00
@loveyou1 #11 报错的原因上面已经有人说了,你的另一种写法不报错是因为在 render 里把 props 定义为 any 了
weixiangzhe
2020-07-05 00:13:11 +08:00
看这个库: https://github.com/typescript-cheatsheets/react-typescript-cheatsheet

children 你定义的是一个 renderprops 写法 对应的是 function 才对,上面的 md 里写的情景很全了,建议看一遍
ke1vin
2020-07-05 01:14:55 +08:00
这不是很明显吗,children 应该是 Function

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/687146

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX